This is an automated email from the ASF dual-hosted git repository.

kmccusker pushed a commit to branch issue34
in repository https://gitbox.apache.org/repos/asf/incubator-milagro-dta.git

commit a32d6264f9c5a162f1f97a9c767874b522d7b5fb
Author: Kealan McCusker <[email protected]>
AuthorDate: Mon Sep 9 14:10:15 2019 +0100

    update the golang crypto wrapper
---
 Dockerfile-alpine                                  |   1 -
 cmd/service/main.go                                |   4 +-
 libs/crypto/libpqnist/CMakeLists.txt               |   2 +-
 libs/crypto/libpqnist/examples/CMakeLists.txt      |   2 +-
 libs/crypto/libpqnist/examples/run_aescbc.c        |   2 +-
 libs/crypto/libpqnist/examples/run_aesgcm.c        |   2 +-
 .../examples/{run_sign_verify.c => run_bls.c}      |  25 +-
 libs/crypto/libpqnist/examples/run_bls_add.c       | 173 +++++++++++
 .../{run_sign_verify_bad.c => run_bls_bad.c}       |  46 ++-
 libs/crypto/libpqnist/examples/run_bls_sss.c       | 176 +++++++++++
 libs/crypto/libpqnist/examples/run_encap_decap.c   |  11 +-
 libs/crypto/libpqnist/examples/run_pqnist.c        |  25 +-
 libs/crypto/libpqnist/include/CMakeLists.txt       |   6 +-
 .../libpqnist/include/{pqnist => amcl}/pqnist.h    | 144 ++++++---
 libs/crypto/libpqnist/src/CMakeLists.txt           |   5 +
 libs/crypto/libpqnist/src/pqnist.c                 | 343 +++++++++++++++-----
 libs/crypto/libpqnist/test/smoke/CMakeLists.txt    |   2 +-
 libs/crypto/libpqnist/test/smoke/test_aescbc.c     |   2 +-
 libs/crypto/libpqnist/test/smoke/test_aesgcm.c     |   2 +-
 .../test/smoke/{test_sign_verify.c => test_bls.c}  |  22 +-
 libs/crypto/libpqnist/test/smoke/test_bls_add.c    | 216 +++++++++++++
 libs/crypto/libpqnist/test/smoke/test_bls_sss.c    | 187 +++++++++++
 .../crypto/libpqnist/test/smoke/test_encap_decap.c |   8 +-
 libs/crypto/libpqnist/test/smoke/test_pqnist.c     |  20 +-
 libs/crypto/libpqnist/test/unit/test_aes_decrypt.c |   2 +-
 libs/crypto/libpqnist/test/unit/test_aes_encrypt.c |   2 +-
 libs/crypto/pqnist.go                              | 346 +++++++++++++++------
 libs/crypto/pqnist_test.go                         | 205 ++++++++++--
 libs/documents/crypto.go                           |   4 +-
 libs/documents/docs_test.go                        |  10 +-
 pkg/defaultservice/identity.go                     |  16 +-
 31 files changed, 1669 insertions(+), 342 deletions(-)

diff --git a/Dockerfile-alpine b/Dockerfile-alpine
index 1583663..36a4243 100644
--- a/Dockerfile-alpine
+++ b/Dockerfile-alpine
@@ -23,7 +23,6 @@ WORKDIR /root
 RUN echo Building Milagro Crypto C library && \
        git clone https://github.com/apache/incubator-milagro-crypto-c.git && \
        cd incubator-milagro-crypto-c && \
-    git checkout 1.0.0 && \
     mkdir build && \
     cd build && \
     cmake \
diff --git a/cmd/service/main.go b/cmd/service/main.go
index 4a289f5..e788374 100644
--- a/cmd/service/main.go
+++ b/cmd/service/main.go
@@ -78,7 +78,7 @@ func initConfig(args []string) error {
                return errors.Wrap(err, "init datastore")
        }
 
-       logger.Info("IPFS connectort type: %s", cfg.IPFS.Connector)
+       logger.Info("IPFS connector type: %s", cfg.IPFS.Connector)
        var ipfsConnector ipfs.Connector
        switch cfg.IPFS.Connector {
        case "api":
@@ -152,7 +152,7 @@ func startDaemon(args []string) error {
                return errors.Wrap(err, "init datastore")
        }
 
-       logger.Info("IPFS connectort type: %s", cfg.IPFS.Connector)
+       logger.Info("IPFS connector type: %s", cfg.IPFS.Connector)
        var ipfsConnector ipfs.Connector
        switch cfg.IPFS.Connector {
        case "api":
diff --git a/libs/crypto/libpqnist/CMakeLists.txt 
b/libs/crypto/libpqnist/CMakeLists.txt
index 7b4177a..76e5db2 100644
--- a/libs/crypto/libpqnist/CMakeLists.txt
+++ b/libs/crypto/libpqnist/CMakeLists.txt
@@ -76,7 +76,7 @@ endif(CMAKE_BUILD_TYPE STREQUAL "Coverage")
 log(CMAKE_INSTALL_PREFIX)
 
 # /include subdir
-set(INSTALL_INCLUDESUBDIR "${CMAKE_INSTALL_INCLUDEDIR}/")
+set(INSTALL_INCLUDESUBDIR "${CMAKE_INSTALL_INCLUDEDIR}/amcl")
 log(CMAKE_INSTALL_INCLUDEDIR)
 log(INSTALL_INCLUDESUBDIR)
 
diff --git a/libs/crypto/libpqnist/examples/CMakeLists.txt 
b/libs/crypto/libpqnist/examples/CMakeLists.txt
index c3d6b0a..b8ff74b 100644
--- a/libs/crypto/libpqnist/examples/CMakeLists.txt
+++ b/libs/crypto/libpqnist/examples/CMakeLists.txt
@@ -2,7 +2,7 @@
 file(GLOB_RECURSE SRCS *.c)
 
 # List of multithreaded examples 
-SET (SRCSTHREAD run_encap_decap.c run_sign_verify.c)
+SET (SRCSTHREAD run_encap_decap.c run_bls.c)
 
 # Add the binary tree directory to the search path for linking and include 
files
 link_directories (${PROJECT_BINARY_DIR}/src
diff --git a/libs/crypto/libpqnist/examples/run_aescbc.c 
b/libs/crypto/libpqnist/examples/run_aescbc.c
index f906cad..6722c46 100644
--- a/libs/crypto/libpqnist/examples/run_aescbc.c
+++ b/libs/crypto/libpqnist/examples/run_aescbc.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 int main()
 {
diff --git a/libs/crypto/libpqnist/examples/run_aesgcm.c 
b/libs/crypto/libpqnist/examples/run_aesgcm.c
index e5d8f1c..1f0be67 100644
--- a/libs/crypto/libpqnist/examples/run_aesgcm.c
+++ b/libs/crypto/libpqnist/examples/run_aesgcm.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define Keylen 32
 #define IVlen 12
diff --git a/libs/crypto/libpqnist/examples/run_sign_verify.c 
b/libs/crypto/libpqnist/examples/run_bls.c
similarity index 79%
rename from libs/crypto/libpqnist/examples/run_sign_verify.c
rename to libs/crypto/libpqnist/examples/run_bls.c
index 68eb758..838ae92 100644
--- a/libs/crypto/libpqnist/examples/run_sign_verify.c
+++ b/libs/crypto/libpqnist/examples/run_bls.c
@@ -18,7 +18,7 @@
 */
 
 /*
-   Sign a message and verify the signature
+   BLS sign a message and verify the signature
 */
 
 #include <stdio.h>
@@ -27,8 +27,7 @@
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
-#include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define NTHREADS 8
 #define MAXSIZE 256
@@ -60,11 +59,7 @@ int main()
         }
     }
 
-    // Generate SIKE and BLS keys
-
-    // Bob's SIKE keys (not used)
-    uint8_t SIKEpk[NTHREADS][OQS_KEM_sike_p751_length_public_key];
-    uint8_t SIKEsk[NTHREADS][OQS_KEM_sike_p751_length_secret_key];
+    // Generate BLS keys
 
     // Alice's BLS keys
     char BLSsk[NTHREADS][BGS_BLS381];
@@ -74,7 +69,7 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
 
-        rc = pqnist_keys(seed[i], SIKEpk[i], SIKEsk[i], BLSpk[i], BLSsk[i]);
+        rc = pqnist_bls_keys(seed[i], BLSpk[i], BLSsk[i]);
         if (rc)
         {
             fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
@@ -114,10 +109,10 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
         // Alice signs message
-        rc = pqnist_sign(P[i].val, BLSsk[i], S[i].val);
+        rc = pqnist_bls_sign(P[i].val, BLSsk[i], S[i].val);
         if(rc)
         {
-            fprintf(stderr, "ERROR pqnist_sign rc: %d\n", rc);
+            fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
             printf("FAILURE\n");
             exit(EXIT_FAILURE);
         }
@@ -131,15 +126,15 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
         // Bob verifies message
-        rc = pqnist_verify(P[i].val, BLSpk[i], S[i].val);
+        rc = pqnist_bls_verify(P[i].val, BLSpk[i], S[i].val);
         if (rc)
         {
-            fprintf(stderr, "ERROR pqnist_verify rc: %d\n", rc);
+            fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
             exit(EXIT_FAILURE);
         }
         else
         {
-            printf("SUCCESS Test %d pqnist_verify rc: %d\n", i, rc);
+            printf("SUCCESS Test %d pqnist_bls_verify rc: %d\n", i, rc);
             OCT_output_string(&P[i]);
             printf("\n");
         }
@@ -148,8 +143,6 @@ int main()
     // clear memory
     for(i=0; i<NTHREADS; i++)
     {
-        OQS_MEM_cleanse(SIKEsk[i], OQS_KEM_sike_p751_length_secret_key);
-        OQS_MEM_cleanse(BLSsk[i], OQS_SIG_picnic_L5_FS_length_secret_key);
         OCT_clear(&P[i]);
         OCT_clear(&S[i]);
     }
diff --git a/libs/crypto/libpqnist/examples/run_bls_add.c 
b/libs/crypto/libpqnist/examples/run_bls_add.c
new file mode 100644
index 0000000..516a85e
--- /dev/null
+++ b/libs/crypto/libpqnist/examples/run_bls_add.c
@@ -0,0 +1,173 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+/*
+   Sign a message and verify the signature. 
+   Generate a public key from externally generated secret key
+   Add public keys and signatures.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <amcl/utils.h>
+#include <amcl/randapi.h>
+#include <amcl/bls_BLS381.h>
+#include <amcl/pqnist.h>
+
+#define G2LEN 4*BFS_BLS381
+#define SIGLEN BFS_BLS381+1
+
+int main()
+{
+    int rc;
+
+    // Message to be signed
+    char message[] = "test message";
+
+    // Seed values for CSPRNG
+    char seed1[PQNIST_SEED_LENGTH];
+    char seed2[PQNIST_SEED_LENGTH];
+
+    // seed values
+    char* seed1Hex = 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150";
+    char* seed2Hex = 
"46389f32b7cdebbbc46b7165d8fae888c9de444898390a939977e1a066256a6f465e7d76307178aef81ae0c6841f9b7c";
+    amcl_hex2bin(seed1Hex, seed1, PQNIST_SEED_LENGTH*2);
+    amcl_hex2bin(seed2Hex, seed2, PQNIST_SEED_LENGTH*2);
+    printf("seed1: ");
+    amcl_print_hex(seed1, PQNIST_SEED_LENGTH);
+    printf("seed2: ");
+    amcl_print_hex(seed2, PQNIST_SEED_LENGTH);
+    printf("\n");
+
+    // BLS keys
+    char sk1[BGS_BLS381];
+    char pktmp[G2LEN];
+    char pk1[G2LEN];    
+    char sk2[BGS_BLS381];
+    char pk2[G2LEN];
+    char pk12[G2LEN];
+
+    // BLS signature
+    char sig1[SIGLEN];
+    char sig2[SIGLEN];
+    char sig12[SIGLEN];
+
+    rc = pqnist_bls_keys(seed1, pktmp, sk1);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_keys(seed2, pk2, sk2);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    // Generate pk from sk 
+    rc = pqnist_bls_keys(NULL, pk1, sk1);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("sk1: ");
+    amcl_print_hex(sk1, BGS_BLS381);    
+    printf("pktmp: ");
+    amcl_print_hex(pktmp, G2LEN);
+    printf("pk1: ");
+    amcl_print_hex(pk1, G2LEN);
+    printf("sk2: ");
+    amcl_print_hex(sk2, BGS_BLS381);    
+    printf("pk2: ");
+    amcl_print_hex(pk2, G2LEN);
+    printf("\n");
+
+    // Sign message
+    rc = pqnist_bls_sign(message, sk1, sig1);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_sign(message, sk2, sig2);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("sig1: ");
+    amcl_print_hex(sig1, SIGLEN);
+    printf("sig2: ");
+    amcl_print_hex(sig2, SIGLEN);
+    printf("\n");
+
+    // Verify message
+    rc = pqnist_bls_verify(message, pk1, sig1);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_verify(message, pk2, sig2);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_addg1(sig1, sig2, sig12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_addg1 rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_addg2(pk1, pk2, pk12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_addg1 rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("pk12: ");
+    amcl_print_hex(pk12, G2LEN);
+    printf("sig12: ");
+    amcl_print_hex(sig12, SIGLEN);
+    printf("\n");
+
+    rc = pqnist_bls_verify(message, pk12, sig12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("TEST PASSED\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/libs/crypto/libpqnist/examples/run_sign_verify_bad.c 
b/libs/crypto/libpqnist/examples/run_bls_bad.c
similarity index 69%
rename from libs/crypto/libpqnist/examples/run_sign_verify_bad.c
rename to libs/crypto/libpqnist/examples/run_bls_bad.c
index fe99eb9..a063609 100644
--- a/libs/crypto/libpqnist/examples/run_sign_verify_bad.c
+++ b/libs/crypto/libpqnist/examples/run_bls_bad.c
@@ -18,7 +18,7 @@
 */
 
 /*
-   Sign a message and verify the signature. Introduce errors.
+   BLS sign a message and verify the signature. Introduce errors.
 */
 
 #include <stdio.h>
@@ -27,8 +27,7 @@
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
-#include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define G2LEN 4*BFS_BLS381
 #define SIGLEN BFS_BLS381+1
@@ -41,9 +40,8 @@ int main()
     char seed[PQNIST_SEED_LENGTH];
 
     // Message to be sent to Bob
-    char p[256];
+    char p[] = "Hello Bob! This is a message from Alice";
     octet P = {0, sizeof(p), p};
-    OCT_jstring(&P,"Hello Bob! This is a message from Alice");
 
     // non random seed value
     for (i=0; i<PQNIST_SEED_LENGTH; i++) seed[i]=i+1;
@@ -51,17 +49,13 @@ int main()
     amcl_print_hex(seed, PQNIST_AES_KEY_LENGTH);
     printf("\n");
 
-    // Generate SIKE and BLS keys
-
-    // Bob's SIKE keys (not used)
-    uint8_t SIKEpk[OQS_KEM_sike_p751_length_public_key];
-    uint8_t SIKEsk[OQS_KEM_sike_p751_length_secret_key];
+    // Generate BLS keys
 
     // Alice's BLS keys
     char BLSsk[BGS_BLS381];
     char BLSpk[G2LEN];
 
-    rc = pqnist_keys(seed, SIKEpk, SIKEsk, BLSpk, BLSsk);
+    rc = pqnist_bls_keys(seed, BLSpk, BLSsk);
     if (rc)
     {
         fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
@@ -78,10 +72,10 @@ int main()
     char S[SIGLEN];
 
     // Alice signs message
-    rc = pqnist_sign(P.val, BLSsk, S);
+    rc = pqnist_bls_sign(P.val, BLSsk, S);
     if(rc != BLS_OK)
     {
-        fprintf(stderr, "ERROR pqnist_sign rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
         printf("FAILURE\n");
         exit(EXIT_FAILURE);
     }
@@ -91,14 +85,14 @@ int main()
     printf("\n");
 
     // Bob verifies message
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
-        printf("SUCCESS pqnist_verify rc: %d\n", rc);
+        printf("SUCCESS pqnist_bls_verify rc: %d\n", rc);
     }
     else
     {
-        fprintf(stderr, "ERROR pqnist_verify rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
         exit(EXIT_FAILURE);
     }
 
@@ -110,14 +104,14 @@ int main()
     // Bob verifies corrupted message. This should fail
     char tmp = P.val[0];
     P.val[0] = 5;
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_FAIL)
     {
-        fprintf(stderr, "ERROR pqnist_verify rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
     }
     else
     {
-        printf("SUCCESS pqnist_verify rc: %d\n", rc);
+        printf("SUCCESS pqnist_bls_verify rc: %d\n", rc);
         printf("TEST FAILED\n");
         exit(EXIT_FAILURE);
     }
@@ -129,36 +123,34 @@ int main()
     printf("\n");
 
     // Check signature is correct
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
-        printf("SUCCESS pqnist_verify rc: %d\n", rc);
+        printf("SUCCESS pqnist_bls_verify rc: %d\n", rc);
     }
     else
     {
-        fprintf(stderr, "ERROR pqnist_verify rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
         printf("TEST FAILED\n");
         exit(EXIT_FAILURE);
     }
 
     // Bob verifies corrupted signature. This should fail
     S[0] = 0;
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_INVALID_G1)
     {
 
-        fprintf(stderr, "ERROR pqnist_verify rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
     }
     else
     {
-        printf("SUCCESS pqnist_verify rc: %d\n", rc);
+        printf("SUCCESS pqnist_bls_verify rc: %d\n", rc);
         printf("TEST FAILED\n");
         exit(EXIT_FAILURE);
     }
 
     // clear memory
-    OQS_MEM_cleanse(SIKEsk, OQS_KEM_sike_p751_length_secret_key);
-    OQS_MEM_cleanse(BLSsk, OQS_SIG_picnic_L5_FS_length_secret_key);
     OCT_clear(&P);
 
     printf("TEST PASSED\n");
diff --git a/libs/crypto/libpqnist/examples/run_bls_sss.c 
b/libs/crypto/libpqnist/examples/run_bls_sss.c
new file mode 100644
index 0000000..53b880b
--- /dev/null
+++ b/libs/crypto/libpqnist/examples/run_bls_sss.c
@@ -0,0 +1,176 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+/*
+   BLS SSS example
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <amcl/utils.h>
+#include <amcl/randapi.h>
+#include <amcl/bls_BLS381.h>
+#include <amcl/pqnist.h>
+
+#define G2LEN 4*BFS_BLS381
+#define SIGLEN BFS_BLS381+1
+
+int main()
+{
+    int rc;
+    int n=4;
+    int k=3;
+
+    // Message to be signed
+    char message[] = "test message";
+
+    // Seed value for CSPRNG
+    char seed1[PQNIST_SEED_LENGTH];
+    char seed2[PQNIST_SEED_LENGTH];
+
+    // seed values
+    char* seed1Hex = 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150";
+    char* seed2Hex = 
"46389f32b7cdebbbc46b7165d8fae888c9de444898390a939977e1a066256a6f465e7d76307178aef81ae0c6841f9b7c";
+    amcl_hex2bin(seed1Hex, seed1, PQNIST_SEED_LENGTH*2);
+    amcl_hex2bin(seed2Hex, seed2, PQNIST_SEED_LENGTH*2);
+    printf("seed1: ");
+    amcl_print_hex(seed1, PQNIST_SEED_LENGTH);
+    printf("\n");
+    printf("seed2: ");
+    amcl_print_hex(seed2, PQNIST_SEED_LENGTH);
+    printf("\n");
+
+    // BLS keys
+    char ski[BGS_BLS381];
+    char sko[BGS_BLS381];
+    char skr[BGS_BLS381];
+    char pki[G2LEN];
+
+    rc = pqnist_bls_keys(seed1, pki, ski);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("pki: ");
+    amcl_print_hex(pki, G2LEN);
+    printf("ski: ");
+    amcl_print_hex(ski, BGS_BLS381);
+    printf("\n");
+
+    // BLS signature
+    char sigi[SIGLEN];
+
+    // Sign message
+    rc = pqnist_bls_sign(message, ski, sigi);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("sigi ");
+    amcl_print_hex(sigi, SIGLEN);
+    printf("\n");
+
+    // Verify signature
+    rc = pqnist_bls_verify(message, pki, sigi);
+    if (rc == BLS_OK)
+    {
+        printf("SUCCESS pqnist_bls_verify rc: %d\n", rc);
+    }
+    else
+    {
+        fprintf(stderr, "ERROR pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    // Secret shares
+    char x[BGS_BLS381*n];
+    char y[BGS_BLS381*n];
+
+    // Make shares of BLS secret key
+    rc = pqnist_bls_make_shares(k, n, seed2, x, y, ski, sko);
+    if (rc!=BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_make_shares rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("ski: ");
+    amcl_print_hex(ski, BGS_BLS381);
+    printf("sko: ");
+    amcl_print_hex(sko, BGS_BLS381);
+    printf("\n");
+
+    for(int i=0; i<n; i++)
+    {
+        printf("x[%d] ", i);
+        amcl_print_hex(&x[i*BGS_BLS381], BGS_BLS381);
+        printf("y[%d] ", i);
+        amcl_print_hex(&y[i*BGS_BLS381], BGS_BLS381);
+        printf("\n");
+    }
+
+    // Recover BLS secret key
+    rc = pqnist_bls_recover_secret(k, x, y, skr);
+    if (rc!=BLS_OK)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_recover_secret rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+    printf("skr: ");
+    amcl_print_hex(skr, BGS_BLS381);
+    printf("\n");
+
+    // Generate public keys and signatures using shares
+    char sigs[(SIGLEN)*n];
+    char sigr[SIGLEN];
+    for(int i=0; i<n; i++)
+    {
+        rc = pqnist_bls_sign(message, &y[BFS_BLS381*i], &sigs[(SIGLEN)*i]);
+        if(rc != BLS_OK)
+        {
+            fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
+            printf("FAILURE\n");
+            exit(EXIT_FAILURE);
+        }
+
+    }
+
+    for(int i=0; i<n; i++)
+    {
+        printf("sigs[%d] ", i);
+        amcl_print_hex(&sigs[i*(SIGLEN)], SIGLEN);
+        printf("\n");
+    }
+
+    // Recover BLS signature
+    pqnist_bls_recover_signature(k, x, sigs, sigr);
+
+    printf("sigr ");
+    amcl_print_hex(sigr, SIGLEN);
+    printf("\n");
+
+    printf("TEST PASSED\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/libs/crypto/libpqnist/examples/run_encap_decap.c 
b/libs/crypto/libpqnist/examples/run_encap_decap.c
index a7da06d..e35691a 100644
--- a/libs/crypto/libpqnist/examples/run_encap_decap.c
+++ b/libs/crypto/libpqnist/examples/run_encap_decap.c
@@ -29,7 +29,7 @@
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
 #include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define NTHREADS 8
 #define MAXSIZE 256
@@ -83,17 +83,13 @@ int main()
     uint8_t SIKEpk[NTHREADS][OQS_KEM_sike_p751_length_public_key];
     uint8_t SIKEsk[NTHREADS][OQS_KEM_sike_p751_length_secret_key];
 
-    // Alice's BLS keys (not used)
-    char BLSpk[NTHREADS][G2LEN];
-    char BLSsk[NTHREADS][BGS_BLS381];
-
     #pragma omp parallel for
     for(i=0; i<NTHREADS; i++)
     {
-        rc = pqnist_keys(seedkeys[i], SIKEpk[i], SIKEsk[i], BLSpk[i], 
BLSsk[i]);
+        rc = pqnist_sike_keys(seedkeys[i], SIKEpk[i], SIKEsk[i]);
         if (rc)
         {
-            fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+            fprintf(stderr, "ERROR pqnist_sike_keys rc: %d\n", rc);
             exit(EXIT_FAILURE);
         }
 
@@ -198,7 +194,6 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
         OQS_MEM_cleanse(SIKEsk[i], OQS_KEM_sike_p751_length_secret_key);
-        OQS_MEM_cleanse(BLSsk[i], OQS_SIG_picnic_L5_FS_length_secret_key);
         OCT_clear(&P[i]);
         OCT_clear(&C[i]);
     }
diff --git a/libs/crypto/libpqnist/examples/run_pqnist.c 
b/libs/crypto/libpqnist/examples/run_pqnist.c
index a82a31d..f5e9a1c 100644
--- a/libs/crypto/libpqnist/examples/run_pqnist.c
+++ b/libs/crypto/libpqnist/examples/run_pqnist.c
@@ -28,7 +28,7 @@
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
 #include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define G2LEN 4*BFS_BLS381
 #define SIGLEN BFS_BLS381+1
@@ -105,10 +105,17 @@ int main()
     char BLSsk[BGS_BLS381];
     char BLSpk[G2LEN];
 
-    rc = pqnist_keys(seed, SIKEpk, SIKEsk, BLSpk, BLSsk);
+    rc = pqnist_sike_keys(seed, SIKEpk, SIKEsk);
     if (rc)
     {
-        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_sike_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_keys(seed, BLSpk, BLSsk);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_bls_keys rc: %d\n", rc);
         exit(EXIT_FAILURE);
     }
 
@@ -223,10 +230,10 @@ int main()
     // Sign message
 
     // Alice signs message
-    rc = pqnist_sign(P.val, BLSsk, S);
+    rc = pqnist_bls_sign(P.val, BLSsk, S);
     if(rc)
     {
-        fprintf(stderr, "ERROR pqnist_sign rc: %d\n", rc);
+        fprintf(stderr, "ERROR pqnist_bls_sign rc: %d\n", rc);
         printf("FAILURE\n");
         exit(EXIT_FAILURE);
     }
@@ -236,7 +243,7 @@ int main()
     printf("\n");
 
     // Bob verifies message
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
         printf("BOB SUCCESS: signature verified\n");
@@ -255,7 +262,7 @@ int main()
     // Bob verifies corrupted message
     char tmp = P.val[0];
     P.val[0] = 0;
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
         printf("BOB SUCCESS: signature verified\n");
@@ -272,7 +279,7 @@ int main()
     printf("\n");
 
     // Check signature is correct
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
         printf("BOB SUCCESS: signature verified\n");
@@ -284,7 +291,7 @@ int main()
 
     // Bob verifies corrupted signature
     S[0] = 0;
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc == BLS_OK)
     {
         printf("BOB SUCCESS: signature verified\n");
diff --git a/libs/crypto/libpqnist/include/CMakeLists.txt 
b/libs/crypto/libpqnist/include/CMakeLists.txt
index 8e60838..194970c 100644
--- a/libs/crypto/libpqnist/include/CMakeLists.txt
+++ b/libs/crypto/libpqnist/include/CMakeLists.txt
@@ -1,5 +1,9 @@
 # List of headers
-file(GLOB headers "pqnist/*.h")
+file(GLOB headers "amcl/*.h")
 
 install(FILES ${headers}
         DESTINATION ${INSTALL_INCLUDESUBDIR})
+
+# Copy header to golang binary directory
+file(COPY ${headers} DESTINATION ${PROJECT_BINARY_DIR}/go/amcl)
+      
diff --git a/libs/crypto/libpqnist/include/pqnist/pqnist.h 
b/libs/crypto/libpqnist/include/amcl/pqnist.h
similarity index 70%
rename from libs/crypto/libpqnist/include/pqnist/pqnist.h
rename to libs/crypto/libpqnist/include/amcl/pqnist.h
index 0989ce1..aaa0461 100644
--- a/libs/crypto/libpqnist/include/pqnist/pqnist.h
+++ b/libs/crypto/libpqnist/include/amcl/pqnist.h
@@ -20,7 +20,7 @@
 /**
  * @file pqnist.h
  * @author Kealan McCusker
- * @brief envelope crypto function declarations
+ * @brief crypto function declarations
  *
  */
 
@@ -36,50 +36,17 @@
 extern "C" {
 #endif
 
-/**  @brief Generate SIKE and BLS keys
+/**  @brief Generate BLS keys
 
-     Generate SIKE and BLS key public and private key pairs
+     Generate BLS public and private key
 
-     @param seed             seed value for CSPRNG - 48 bytes
-     @param SIKEpk           SIKE public key
-     @param SIKEsk           SIKE secret key
+     @param seed             seed value for CSPRNG
      @param BLSpk            BLS public key
-     @param BLSsk            BLS secret key
+     @param BLSsk            BLS secret key. Generated externally if seed set 
to NULL
      @return                 Zero for success or else an error code
  */
-int pqnist_keys(char* seed, char* SIKEpk, char* SIKEsk, char* BLSpk, char* 
BLSsk);
-
-/**  @brief Encrypt a message and encapsulate the AES Key for
-     a recipient.
+int pqnist_bls_keys(char* seed, char* BLSpk, char* BLSsk);
 
-     The  message is encrypted using AES-256. The key
-     is generated inside this function as an output
-     from the encapsulation function. The ciphertext
-     is returned using the P paramter.
-
-     @param P            Plaintext to be encrypted / Ciphertext. Padded with 
zero.
-     @param Plen         Plaintext length in bytes must be a multiple of the 
block size (16)
-     @param IV           Initialization vector IV (16 bytes)
-     @param pk           SIKE public key
-     @param ek           Encapsulated key
-     @return             Zero for success or else an error code
- */
-int pqnist_encapsulate_encrypt(char* P, int Plen, char* IV, char* pk, char* 
ek);
-
-/**  @brief Decapsulate the AES Key and decrypt the message
-
-     Decapsulate the AES key and use it to decrypt the
-     ciphertext. The plaintext is returned using the C
-     parameter.
-
-     @param C            Ciphertext to be decrypted / Plaintext
-     @param Clen         Ciphertext length in bytes must be a multiple of the 
block size (16)
-     @param IV           Initialization vector IV
-     @param sk           SIKE secret key
-     @param ek           Encapsulated key
-     @return             Zero for success or else an error code
- */
-int pqnist_decapsulate_decrypt(char* C, int Clen, char* IV, char* sk, char* 
ek);
 
 /**  @brief Sign a message
 
@@ -90,7 +57,7 @@ int pqnist_decapsulate_decrypt(char* C, int Clen, char* IV, 
char* sk, char* ek);
      @param S            Signature
      @return             Zero for success or else an error code
  */
-int pqnist_sign(char* M, char* sk, char* S);
+int pqnist_bls_sign(char* M, char* sk, char* S);
 
 /**  @brief Verify a signature
 
@@ -101,7 +68,59 @@ int pqnist_sign(char* M, char* sk, char* S);
      @param S            Signature
      @return             Zero for success or else an error code
  */
-int pqnist_verify(char* M, char* pk, char* S);
+int pqnist_bls_verify(char* M, char* pk, char* S);
+
+/**    @brief Add two members from the group G1
+ *
+       @param  r1  member of G1
+       @param  r2  member of G1
+       @param  r   member of G1. r = r1+r2
+       @return     Zero for success or else an error code
+ */
+int pqnist_bls_addg1(char* r1, char* r2, char* r);
+
+/**    @brief Add two members from the group G2
+ *
+       @param  r1  member of G2
+       @param  r2  member of G2
+       @param  r   member of G2. r = r1+r2
+       @return     Zero for success or else an error code
+ */
+int pqnist_bls_addg2(char* r1, char* r2, char* r);
+
+
+/**    @brief Use Shamir's secret sharing to distribute BLS secret keys
+ *
+       @param  k       Threshold
+       @param  n       Number of shares
+        @param  pSEED   seed value for CSPRNG - 48 bytes
+       @param  pX      X values
+       @param  pY      Y values. Valid BLS secret keys
+       @param  pSKI    Input secret key to be shared. Ignored if set to NULL
+       @param  pSKO    Secret key that is shared
+       @return         Zero for success or else an error code
+ */
+int pqnist_bls_make_shares(int k, int n,  char* pSEED, char* pX, char* pY, 
char* pSKI, char* pSKO);
+
+/**    @brief Use Shamir's secret sharing to recover a BLS secret key
+ *
+       @param  k    Threshold
+       @param  pX   X values
+       @param  pY   Y values. Valid BLS secret keys
+       @param  pSK  Secret key that is recovered
+       @return      Zero for success or else an error code
+ */
+int pqnist_bls_recover_secret(int k, char* pX, char* pY, char* pSK);
+
+/**    @brief Use Shamir's secret sharing to recover a BLS signature
+ *
+       @param  k     Threshold
+       @param  pX    X values
+       @param  pY    Y values. Valid BLS signatures
+       @param  pSIG  Signature that is recovered
+       @return       Zero for success or else an error code
+ */
+int pqnist_bls_recover_signature(int k, char* pX, char* pY, char* pSIG);
 
 /**  @brief AES-GCM Encryption
 
@@ -161,6 +180,49 @@ void pqnist_aes_cbc_encrypt(char* K, int Klen, char* IV, 
char* P, int Plen);
  */
 void pqnist_aes_cbc_decrypt(char* K, int Klen, char* IV, char* C, int Clen);
 
+/**  @brief Generate SIKE keys
+
+     Generate SIKE public and private key
+
+     @param seed             seed value for CSPRNG - 48 bytes
+     @param SIKEpk           SIKE public key
+     @param SIKEsk           SIKE secret key
+     @return                 Zero for success or else an error code
+ */
+int pqnist_sike_keys(char* seed, char* SIKEpk, char* SIKEsk);
+
+/**  @brief Encrypt a message and encapsulate the AES Key for
+     a recipient.
+
+     The  message is encrypted using AES-256. The key
+     is generated inside this function as an output
+     from the encapsulation function. The ciphertext
+     is returned using the P paramter.
+
+     @param P            Plaintext to be encrypted / Ciphertext. Padded with 
zero.
+     @param Plen         Plaintext length in bytes must be a multiple of the 
block size (16)
+     @param IV           Initialization vector IV (16 bytes)
+     @param pk           SIKE public key
+     @param ek           Encapsulated key
+     @return             Zero for success or else an error code
+ */
+int pqnist_encapsulate_encrypt(char* P, int Plen, char* IV, char* pk, char* 
ek);
+
+/**  @brief Decapsulate the AES Key and decrypt the message
+
+     Decapsulate the AES key and use it to decrypt the
+     ciphertext. The plaintext is returned using the C
+     parameter.
+
+     @param C            Ciphertext to be decrypted / Plaintext
+     @param Clen         Ciphertext length in bytes must be a multiple of the 
block size (16)
+     @param IV           Initialization vector IV
+     @param sk           SIKE secret key
+     @param ek           Encapsulated key
+     @return             Zero for success or else an error code
+ */
+int pqnist_decapsulate_decrypt(char* C, int Clen, char* IV, char* sk, char* 
ek);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/crypto/libpqnist/src/CMakeLists.txt 
b/libs/crypto/libpqnist/src/CMakeLists.txt
index 40a9ca3..1480553 100644
--- a/libs/crypto/libpqnist/src/CMakeLists.txt
+++ b/libs/crypto/libpqnist/src/CMakeLists.txt
@@ -23,3 +23,8 @@ install(TARGETS ${target} DESTINATION lib PERMISSIONS
         GROUP_READ GROUP_EXECUTE
         WORLD_READ WORLD_EXECUTE)
 
+message(STATUS "Copy ${target} library to go for testing")
+add_custom_command(TARGET ${target} POST_BUILD
+                   COMMAND ${CMAKE_COMMAND} -E copy
+                          "${CMAKE_CURRENT_BINARY_DIR}/lib*"
+                          "${PROJECT_BINARY_DIR}/go/")
diff --git a/libs/crypto/libpqnist/src/pqnist.c 
b/libs/crypto/libpqnist/src/pqnist.c
index 7054e7e..2bb4565 100644
--- a/libs/crypto/libpqnist/src/pqnist.c
+++ b/libs/crypto/libpqnist/src/pqnist.c
@@ -21,7 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
@@ -29,14 +29,165 @@
 #define G2LEN 4*BFS_BLS381
 #define SIGLEN BFS_BLS381+1
 
-// #define DEBUGDEV
+//  Generate BLS public and private key
+int pqnist_bls_keys(char* seed, char* BLSpk, char* BLSsk)
+{
+    int rc;
+
+    octet PK = {0,G2LEN,BLSpk};
+    octet SK = {0,BGS_BLS381,BLSsk};
+
+    if (seed==NULL)
+    {
+        rc =  BLS_BLS381_KEY_PAIR_GENERATE(NULL,&SK,&PK);
+    }
+    else
+    {
+        octet SEED = {PQNIST_SEED_LENGTH,PQNIST_SEED_LENGTH,seed};
+
+        // CSPRNG
+        csprng RNG;
+
+        // initialise strong RNG
+        CREATE_CSPRNG(&RNG,&SEED);
+
+        // Generate BLS key pair
+        rc =  BLS_BLS381_KEY_PAIR_GENERATE(&RNG,&SK,&PK);
+    }
+
+    if (rc)
+    {
+        return rc;
+    }
+
+#ifdef DEBUG
+    printf("pqnist_keys BLSpklen %d BLSpk ", PK.len);
+    OCT_output(&PK);
+    printf("pqnist_keys BLSsklen %d BLSsk ", SK.len);
+    OCT_output(&SK);
+#endif
+
+    return 0;
+}
+
+
+//  Sign message using the BLS algorithm
+int pqnist_bls_sign(char* M, char* sk, char* S)
+{
+    octet SIG = {0,SIGLEN,S};
+    octet SK = {BGS_BLS381,BGS_BLS381,sk};
+
+#ifdef DEBUG
+    printf("pqnist_bls_sign SK: ");
+    OCT_output(&SK);
+#endif
+
+    int rc = BLS_BLS381_SIGN(&SIG,M,&SK);
+    if (rc!=BLS_OK)
+    {
+        return rc;
+    }
+
+#ifdef DEBUG
+    printf("pqnist_bls_sign SIG: ");
+    OCT_output(&SIG);
+#endif
+
+    return 0;
+}
+
+//  Verify a signature using the BLS algorithm
+int pqnist_bls_verify(char* M, char* pk, char* S)
+{
+    octet SIG = {SIGLEN,SIGLEN,S};
+    octet PK = {G2LEN,G2LEN,pk};
+
+#ifdef DEBUG
+    printf("pqnist_bls_verify M %s\n", M);
+    printf("pqnist_bls_verify PK: ");
+    OCT_output(&PK);
+    printf("pqnist_bls_verify SIG: ");
+    OCT_output(&SIG);
+#endif
+
+    int rc=BLS_BLS381_VERIFY(&SIG,M,&PK);
+    if (rc!=BLS_OK)
+    {
+        return rc;
+    }
+
+    return 0;
+}
+
+//  Add two members from the group G1
+int pqnist_bls_addg1(char* r1, char* r2, char* r)
+{
+    octet R1 = {BGS_BLS381,BGS_BLS381,r1};
+    octet R2 = {BGS_BLS381,BGS_BLS381,r2};
+    octet R = {BGS_BLS381,BGS_BLS381,r};
+
+    int rc=BLS_BLS381_ADD_G1(&R1,&R2,&R);
+    if (rc!=BLS_OK)
+    {
+        return rc;
+    }
+
+#ifdef DEBUG
+    printf("pqnist_bls_addg1 R1: ");
+    OCT_output(&R1);
+    printf("pqnist_bls_addg1 R2: ");
+    OCT_output(&R2);
+    printf("pqnist_bls_addg1 R: ");
+    OCT_output(&R);
+#endif
 
-//   Generate SIKE and BLS public and private key pairs
-int pqnist_keys(char* seed, char* SIKEpk, char* SIKEsk, char* BLSpk, char* 
BLSsk)
+    return 0;
+}
+
+//  Add two members from the group G2
+int pqnist_bls_addg2(char* r1, char* r2, char* r)
+{
+    octet R1 = {G2LEN,G2LEN,r1};
+    octet R2 = {G2LEN,G2LEN,r2};
+    octet R = {G2LEN,G2LEN,r};
+
+    int rc=BLS_BLS381_ADD_G2(&R1,&R2,&R);
+    if (rc!=BLS_OK)
+    {
+        return rc;
+    }
+
+#ifdef DEBUG
+    printf("pqnist_bls_addg2 R1: ");
+    OCT_output(&R1);
+    printf("pqnist_bls_addg2 R2: ");
+    OCT_output(&R2);
+    printf("pqnist_bls_addg2 R: ");
+    OCT_output(&R);
+#endif
+
+    return 0;
+}
+
+// Use Shamir's secret sharing to distribute BLS secret keys
+int pqnist_bls_make_shares(int k, int n,  char* pSEED, char* pX, char* pY, 
char* pSKI, char* pSKO)
 {
     int rc;
 
-    octet SEED = {PQNIST_SEED_LENGTH,PQNIST_SEED_LENGTH,seed};
+    octet SEED = {PQNIST_SEED_LENGTH,PQNIST_SEED_LENGTH,pSEED};
+    octet SKI = {BGS_BLS381,BGS_BLS381,pSKI};
+    octet SKO = {BGS_BLS381,BGS_BLS381,pSKO};
+    octet X[n];
+    octet Y[n];
+    for(int i=0; i<n; i++)
+    {
+        Y[i].max = BGS_BLS381;
+        Y[i].len = BGS_BLS381;
+        Y[i].val = &pY[i*BGS_BLS381];
+        X[i].max = BGS_BLS381;
+        X[i].len = BGS_BLS381;
+        X[i].val = &pX[i*BGS_BLS381];
+    }
 
     // CSPRNG
     csprng RNG;
@@ -44,24 +195,117 @@ int pqnist_keys(char* seed, char* SIKEpk, char* SIKEsk, 
char* BLSpk, char* BLSsk
     // initialise strong RNG
     CREATE_CSPRNG(&RNG,&SEED);
 
-    octet PK = {0,G2LEN,BLSpk};
-    octet SK = {0,BGS_BLS381,BLSsk};
+    // Make shares of BLS secret key
+    rc = BLS_BLS381_MAKE_SHARES(k, n, &RNG, X, Y, &SKI, &SKO);
+    if (rc)
+    {
+        return rc;
+    }
 
-    // Initialise KAT RNG
-    rc = OQS_randombytes_switch_algorithm(OQS_RAND_alg_nist_kat);
-    if (rc != OQS_SUCCESS)
+#ifdef DEBUG
+    printf("pqnist_keys SEED: ");
+    OCT_output(&SEED);
+    printf("\n");
+
+    for(int i=0; i<n; i++)
+    {
+        printf("X[%d] ", i);
+        OCT_output(&X[i]);
+        printf("Y[%d] ", i);
+        OCT_output(&Y[i]);
+        printf("\n");
+    }
+
+    printf("SKI: ");
+    OCT_output(&SKI);
+    printf("SKO: ");
+    OCT_output(&SKO);
+#endif
+
+    return 0;
+}
+
+// Use Shamir's secret sharing to recover a BLS secret key
+int pqnist_bls_recover_secret(int k, char* pX, char* pY, char* pSK)
+{
+    int rc;
+
+    octet SK = {BGS_BLS381,BGS_BLS381,pSK};
+    octet X[k];
+    octet Y[k];
+    for(int i=0; i<k; i++)
+    {
+        Y[i].max = BGS_BLS381;
+        Y[i].len = BGS_BLS381;
+        Y[i].val = &pY[i*BGS_BLS381];
+        X[i].max = BGS_BLS381;
+        X[i].len = BGS_BLS381;
+        X[i].val = &pX[i*BGS_BLS381];
+    }
+
+    // Recover BLS secret key
+    rc = BLS_BLS381_RECOVER_SECRET(k, X, Y, &SK);
+    if (rc)
     {
         return rc;
     }
-    OQS_randombytes_nist_kat_init(seed, NULL, 256);
 
-    // Generate BLS key pair
-    rc =  BLS_BLS381_KEY_PAIR_GENERATE(&RNG,&SK,&PK);
+#ifdef DEBUG
+    printf("SK: ");
+    OCT_output(&SK);
+#endif
+
+    return 0;
+}
+
+// Use Shamir's secret sharing to recover a BLS signature
+int pqnist_bls_recover_signature(int k, char* pX, char* pY, char* pSIG)
+{
+    int rc;
+
+    octet SIG = {SIGLEN,SIGLEN,pSIG};
+
+    octet X[k];
+    octet Y[k];
+    for(int i=0; i<k; i++)
+    {
+        Y[i].max = SIGLEN;
+        Y[i].len = SIGLEN;
+        Y[i].val = &pY[(SIGLEN)*i];
+        X[i].max = BGS_BLS381;
+        X[i].len = BGS_BLS381;
+        X[i].val = &pX[BGS_BLS381*i];
+    }
+
+    // Recover BLS signature
+    rc = BLS_BLS381_RECOVER_SIGNATURE(k, X, Y, &SIG);
     if (rc)
     {
         return rc;
     }
 
+#ifdef DEBUG
+    printf("pqnist_bls_recover_signature SIG: ");
+    OCT_output(&SIG);
+#endif
+
+    return 0;
+}
+
+
+// Generate SIKE and BLS public and private key pairs
+int pqnist_sike_keys(char* seed, char* SIKEpk, char* SIKEsk)
+{
+    int rc;
+
+    // Initialise KAT RNG
+    rc = OQS_randombytes_switch_algorithm(OQS_RAND_alg_nist_kat);
+    if (rc != OQS_SUCCESS)
+    {
+        return rc;
+    }
+    OQS_randombytes_nist_kat_init(seed, NULL, 256);
+
     // Generate SIKE key pair
     rc = OQS_KEM_sike_p751_keypair(SIKEpk, SIKEsk);
     if (rc != OQS_SUCCESS)
@@ -70,16 +314,7 @@ int pqnist_keys(char* seed, char* SIKEpk, char* SIKEsk, 
char* BLSpk, char* BLSsk
     }
 
 
-#ifdef DEBUGDEV
-    printf("pqnist_keys SEED: ");
-    OCT_output(&SEED);
-    printf("\n");
-
-    printf("pqnist_keys BLSpklen %d BLSpk ", PK.len);
-    OCT_output(&PK);
-    printf("pqnist_keys BLSsklen %d BLSsk ", SK.len);
-    OCT_output(&SK);
-
+#ifdef DEBUG
     int i = OQS_KEM_sike_p751_length_public_key;
     printf("pqnist_keys SIKEpklen %d SIKEpk: ", i);
     amcl_print_hex(SIKEpk, i);
@@ -92,6 +327,7 @@ int pqnist_keys(char* seed, char* SIKEpk, char* SIKEsk, 
char* BLSpk, char* BLSsk
     return 0;
 }
 
+
 /*   The  message is encrypted using AES-256. The key
      is generated inside this function as an output
      from the encapsulation function.
@@ -101,7 +337,7 @@ int pqnist_encapsulate_encrypt(char* P, int Plen, char* IV, 
char* pk, char* ek)
     // AES-256 key
     uint8_t K[OQS_KEM_sike_p751_length_shared_secret];
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("Plaintext %d P: ", Plen);
     amcl_print_hex(P, Plen);
     int i = OQS_KEM_sike_p751_length_public_key;
@@ -116,7 +352,7 @@ int pqnist_encapsulate_encrypt(char* P, int Plen, char* IV, 
char* pk, char* ek)
         return rc;
     }
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     i = OQS_KEM_sike_p751_length_ciphertext;
     printf("ek1 %d ek1: ", i);
     amcl_print_hex(ek, i);
@@ -128,7 +364,7 @@ int pqnist_encapsulate_encrypt(char* P, int Plen, char* IV, 
char* pk, char* ek)
     // Encrypt plaintext
     pqnist_aes_cbc_encrypt(K, PQNIST_AES_KEY_LENGTH, IV, P, Plen);
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("K: ");
     amcl_print_hex(K, PQNIST_AES_KEY_LENGTH);
     printf("IV: ");
@@ -158,7 +394,7 @@ int pqnist_decapsulate_decrypt(char* C, int Clen, char* IV, 
char* sk, char* ek)
         return rc;
     }
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     int i = OQS_KEM_sike_p751_length_shared_secret;
     printf("sec1 %d sec1: ", i);
     amcl_print_hex(sec, i);
@@ -172,51 +408,6 @@ int pqnist_decapsulate_decrypt(char* C, int Clen, char* 
IV, char* sk, char* ek)
     return 0;
 }
 
-//  Sign message using the BLS algorithm
-int pqnist_sign(char* M, char* sk, char* S)
-{
-    octet SIG = {0,SIGLEN,S};
-    octet SK = {BGS_BLS381,BGS_BLS381,sk};
-
-    int rc = BLS_BLS381_SIGN(&SIG,M,&SK);
-    if (rc!=BLS_OK)
-    {
-        return rc;
-    }
-
-#ifdef DEBUGDEV
-    printf("pqnist_sign SIG: ");
-    OCT_output(&SIG);
-#endif
-
-    return 0;
-}
-
-//  Verify a signature using the BLS algorithm
-int pqnist_verify(char* M, char* pk, char* S)
-{
-    octet SIG = {SIGLEN,SIGLEN,S};
-    octet PK = {G2LEN,G2LEN,pk};
-
-#ifdef DEBUGDEV
-    printf("pqnist_verify M %s\n", M);
-    printf("pqnist_verify PK: ");
-    OCT_output(&PK);
-    printf("pqnist_verify SIG: ");
-    OCT_output(&SIG);
-#endif
-
-    int rc=BLS_BLS381_VERIFY(&SIG,M,&PK);
-    if (rc!=BLS_OK)
-    {
-        return rc;
-    }
-
-
-    return 0;
-
-}
-
 //  AES encryption using GCM mode
 void pqnist_aes_gcm_encrypt(char* K, int Klen, char* IV, int IVlen, char* A, 
int Alen, char* P, int Plen, char* C, char* T)
 {
@@ -240,7 +431,7 @@ void pqnist_aes_gcm_decrypt(char* K, int Klen, char* IV, 
int IVlen, char* A, int
 //   AES encryption using CBC mode
 void pqnist_aes_cbc_encrypt(char* K, int Klen, char* IV, char* P, int Plen)
 {
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("pqnist_aes_cbc_encrypt Klen %d K: \n", Klen);
     amcl_print_hex(K, Klen);
     printf("pqnist_aes_cbc_encrypt IVlen %d IV: \n", PQNIST_AES_IV_LENGTH);
@@ -257,7 +448,7 @@ void pqnist_aes_cbc_encrypt(char* K, int Klen, char* IV, 
char* P, int Plen)
         AES_encrypt(&a,&P[i*blockSize]);
     }
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("pqnist_aes_cbc_encrypt Clen %d C: \n", Plen);
     amcl_print_hex(P, Plen);
 #endif
@@ -267,7 +458,7 @@ void pqnist_aes_cbc_encrypt(char* K, int Klen, char* IV, 
char* P, int Plen)
 //   AES decryption using CBC mode
 void pqnist_aes_cbc_decrypt(char* K, int Klen, char* IV, char* C, int Clen)
 {
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("pqnist_aes_cbc_decrypt Klen %d K: \n", Klen);
     amcl_print_hex(K, Klen);
     printf("pqnist_aes_cbc_decrypt IVlen %d IV: \n", PQNIST_AES_IV_LENGTH);
@@ -284,7 +475,7 @@ void pqnist_aes_cbc_decrypt(char* K, int Klen, char* IV, 
char* C, int Clen)
         AES_decrypt(&a,&C[i*blockSize]);
     }
 
-#ifdef DEBUGDEV
+#ifdef DEBUG
     printf("pqnist_aes_cbc_decrypt Plen %d P: \n", Clen);
     amcl_print_hex(C, Clen);
 #endif
diff --git a/libs/crypto/libpqnist/test/smoke/CMakeLists.txt 
b/libs/crypto/libpqnist/test/smoke/CMakeLists.txt
index c85e8e1..82fc259 100644
--- a/libs/crypto/libpqnist/test/smoke/CMakeLists.txt
+++ b/libs/crypto/libpqnist/test/smoke/CMakeLists.txt
@@ -2,7 +2,7 @@
 file(GLOB_RECURSE SRCS *.c)
 
 # List of multithreaded examples 
-SET (SRCSTHREAD test_encap_decap.c test_sign_verify.c)
+SET (SRCSTHREAD test_encap_decap.c test_bls.c)
 
 # Add the binary tree directory to the search path for linking and include 
files
 link_directories (${PROJECT_BINARY_DIR}/src
diff --git a/libs/crypto/libpqnist/test/smoke/test_aescbc.c 
b/libs/crypto/libpqnist/test/smoke/test_aescbc.c
index 4909855..e814291 100644
--- a/libs/crypto/libpqnist/test/smoke/test_aescbc.c
+++ b/libs/crypto/libpqnist/test/smoke/test_aescbc.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 int main()
 {
diff --git a/libs/crypto/libpqnist/test/smoke/test_aesgcm.c 
b/libs/crypto/libpqnist/test/smoke/test_aesgcm.c
index 5e80716..e4b7e82 100644
--- a/libs/crypto/libpqnist/test/smoke/test_aesgcm.c
+++ b/libs/crypto/libpqnist/test/smoke/test_aesgcm.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define Keylen 32
 #define IVlen 12
diff --git a/libs/crypto/libpqnist/test/smoke/test_sign_verify.c 
b/libs/crypto/libpqnist/test/smoke/test_bls.c
similarity index 81%
rename from libs/crypto/libpqnist/test/smoke/test_sign_verify.c
rename to libs/crypto/libpqnist/test/smoke/test_bls.c
index c28b5b0..8923da9 100644
--- a/libs/crypto/libpqnist/test/smoke/test_sign_verify.c
+++ b/libs/crypto/libpqnist/test/smoke/test_bls.c
@@ -27,8 +27,7 @@
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
-#include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define NTHREADS 8
 #define MAXSIZE 256
@@ -60,11 +59,7 @@ int main()
         }
     }
 
-    // Generate SIKE and BLS keys
-
-    // Bob's SIKE keys (not used)
-    uint8_t SIKEpk[NTHREADS][OQS_KEM_sike_p751_length_public_key];
-    uint8_t SIKEsk[NTHREADS][OQS_KEM_sike_p751_length_secret_key];
+    // Generate BLS keys
 
     // Alice's BLS keys
     char BLSsk[NTHREADS][BGS_BLS381];
@@ -74,7 +69,7 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
 
-        rc = pqnist_keys(seed[i], SIKEpk[i], SIKEsk[i], BLSpk[i], BLSsk[i]);
+        rc = pqnist_bls_keys(seed[i], BLSpk[i], BLSsk[i]);
         if (rc)
         {
             fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
@@ -113,10 +108,10 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
         // Alice signs message
-        rc = pqnist_sign(P[i].val, BLSsk[i], S[i].val);
+        rc = pqnist_bls_sign(P[i].val, BLSsk[i], S[i].val);
         if(rc)
         {
-            fprintf(stderr, "FAILURE pqnist_sign rc: %d\n", rc);
+            fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
             exit(EXIT_FAILURE);
         }
         printf("Alice SIGlen %d  SIG", S[i].len);
@@ -128,15 +123,15 @@ int main()
     for(i=0; i<NTHREADS; i++)
     {
         // Bob verifies message
-        rc = pqnist_verify(P[i].val, BLSpk[i], S[i].val);
+        rc = pqnist_bls_verify(P[i].val, BLSpk[i], S[i].val);
         if (rc)
         {
-            fprintf(stderr, "FAILURE pqnist_verify rc: %d\n", rc);
+            fprintf(stderr, "FAILURE pqnist_bls_verify rc: %d\n", rc);
             exit(EXIT_FAILURE);
         }
         else
         {
-            printf("Test %d pqnist_verify rc: %d\n", i, rc);
+            printf("Test %d pqnist_bls_verify rc: %d\n", i, rc);
             OCT_output_string(&P[i]);
             printf("\n");
         }
@@ -145,7 +140,6 @@ int main()
     // clear memory
     for(i=0; i<NTHREADS; i++)
     {
-        OQS_MEM_cleanse(SIKEsk[i], OQS_KEM_sike_p751_length_secret_key);
         OCT_clear(&P[i]);
         OCT_clear(&S[i]);
     }
diff --git a/libs/crypto/libpqnist/test/smoke/test_bls_add.c 
b/libs/crypto/libpqnist/test/smoke/test_bls_add.c
new file mode 100644
index 0000000..956f455
--- /dev/null
+++ b/libs/crypto/libpqnist/test/smoke/test_bls_add.c
@@ -0,0 +1,216 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+/*
+   Sign a message and verify the signature. 
+   Generate a public key from externally generated secret key
+   Add public keys and signatures.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <amcl/utils.h>
+#include <amcl/randapi.h>
+#include <amcl/bls_BLS381.h>
+#include <amcl/pqnist.h>
+
+#define G2LEN 4*BFS_BLS381
+#define SIGLEN BFS_BLS381+1
+
+int main()
+{
+    int rc;
+
+    // Seed values for CSPRNG
+    char seed1[PQNIST_SEED_LENGTH];
+    char seed2[PQNIST_SEED_LENGTH];
+
+    // Message to be signed
+    char message[] = "test message";
+
+    // seed values
+    char* seed1Hex = 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150";
+    char* seed2Hex = 
"46389f32b7cdebbbc46b7165d8fae888c9de444898390a939977e1a066256a6f465e7d76307178aef81ae0c6841f9b7c";
+    amcl_hex2bin(seed1Hex, seed1, PQNIST_SEED_LENGTH*2);
+    amcl_hex2bin(seed2Hex, seed2, PQNIST_SEED_LENGTH*2);
+    printf("seed1: ");
+    amcl_print_hex(seed1, PQNIST_SEED_LENGTH);
+    printf("seed2: ");
+    amcl_print_hex(seed2, PQNIST_SEED_LENGTH);
+    printf("\n");
+
+    // BLS keys
+    char sk1[BGS_BLS381];
+    char pktmp[G2LEN];    
+    char pk1[G2LEN];
+    char sk2[BGS_BLS381];
+    char pk2[G2LEN];
+    char pk12[G2LEN];
+
+    // BLS signature
+    char sig1[SIGLEN];
+    char sig2[SIGLEN];
+    char sig12[SIGLEN];
+
+    rc = pqnist_bls_keys(seed1, pktmp, sk1);
+    if (rc)
+    {
+        fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_keys(seed2, pk2, sk2);
+    if (rc)
+    {
+        fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    // Generate pk from sk 
+    rc = pqnist_bls_keys(NULL, pk1, sk1);
+    if (rc)
+    {
+        fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }    
+
+    printf("sk1: ");
+    amcl_print_hex(sk1, BGS_BLS381);    
+    printf("pktmp: ");
+    amcl_print_hex(pktmp, G2LEN);
+    printf("pk1: ");
+    amcl_print_hex(pk1, G2LEN);
+    printf("sk2: ");
+    amcl_print_hex(sk2, BGS_BLS381);    
+    printf("pk2: ");
+    amcl_print_hex(pk2, G2LEN);
+    printf("\n");
+
+    octet PK1 = {sizeof(pk1),sizeof(pk1),pk1};
+    octet PKTMP = {sizeof(pktmp),sizeof(pktmp),pktmp};    
+    rc = OCT_comp(&PK1,&PKTMP);
+    if(!rc)
+    {
+        fprintf(stderr, "FAILURE PK1 != PKTMP rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+    
+    // Sign message
+    rc = pqnist_bls_sign(message, sk1, sig1);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_sign(message, sk2, sig2);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("sig1: ");
+    amcl_print_hex(sig1, SIGLEN);
+    printf("sig2: ");
+    amcl_print_hex(sig2, SIGLEN);
+    printf("\n");
+
+    // Verify message
+    rc = pqnist_bls_verify(message, pk1, sig1);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_verify(message, pk2, sig2);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_addg1(sig1, sig2, sig12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_addg1 rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_addg2(pk1, pk2, pk12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_addg1 rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("pk12: ");
+    amcl_print_hex(pk12, G2LEN);
+    printf("sig12: ");
+    amcl_print_hex(sig12, SIGLEN);
+    printf("\n");
+
+    rc = pqnist_bls_verify(message, pk12, sig12);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    char* pk12GoldenHex = 
"0fff41dc3b28fee38f564158f9e391a5c6ac42179fcccdf5ee4513030b6d59900a832f9a886b2407dc8b0a3b51921326123d3974bd1864fb22f5a84e83f1f9f611ee082ed5bd6ca896d464f12907ba8acdf15c44f9cff2a2dbb3b32259a1fe4f11d470158066087363df20a11144d6521cf72dca1a7514154a95c7fe73b219989cc40d7fc7e0b97854fc3123c0cf50ae0452730996a5cb24641aff7102fcbb2af705d0f32d5787ca1c3654e4ae6aa59106e1e22e29018ba7c341f1e6472f800f";
+    char* sig12GoldenHex = 
"0203799dc2941b810985d9eb694a5be4a1ad5817f9e5d7c31870bb9fb471f7353eafacdc548544f9e7b78a0a9372c63ab0";
+
+    char pk12golden[G2LEN];
+    octet PK12GOLDEN = {sizeof(pk12golden),sizeof(pk12golden),pk12golden};
+
+    char sig12golden[SIGLEN];
+    octet SIG12GOLDEN = {sizeof(sig12golden),sizeof(sig12golden),sig12golden};
+
+    OCT_fromHex(&PK12GOLDEN,pk12GoldenHex);
+    printf("PK12GOLDEN: ");
+    OCT_output(&PK12GOLDEN);
+
+    OCT_fromHex(&SIG12GOLDEN,sig12GoldenHex);
+    printf("SIG12GOLDEN: ");
+    OCT_output(&SIG12GOLDEN);
+
+    octet PK12 = {sizeof(pk12),sizeof(pk12),pk12};
+    octet SIG12 = {sizeof(sig12),sizeof(sig12),sig12};
+
+    rc = OCT_comp(&PK12GOLDEN,&PK12);
+    if(!rc)
+    {
+        fprintf(stderr, "FAILURE PK12 != PK12GOLDEN rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    rc = OCT_comp(&SIG12GOLDEN,&SIG12);
+    if(!rc)
+    {
+        fprintf(stderr, "FAILURE SIG12 != SIG12GOLDEN rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/libs/crypto/libpqnist/test/smoke/test_bls_sss.c 
b/libs/crypto/libpqnist/test/smoke/test_bls_sss.c
new file mode 100644
index 0000000..21d44ae
--- /dev/null
+++ b/libs/crypto/libpqnist/test/smoke/test_bls_sss.c
@@ -0,0 +1,187 @@
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+
+/*
+   BLS SSS example
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <amcl/utils.h>
+#include <amcl/randapi.h>
+#include <amcl/bls_BLS381.h>
+#include <amcl/pqnist.h>
+
+#define G2LEN 4*BFS_BLS381
+#define SIGLEN BFS_BLS381+1
+
+int main()
+{
+    int rc;
+    int n=4;
+    int k=3;
+
+    // Seed value for CSPRNG
+    char seed[PQNIST_SEED_LENGTH];
+
+    // Message to be sent to Bob
+    char p[] = "This is a test message";
+    octet P = {0, sizeof(p), p};
+
+    // non random seed value
+    for (int i=0; i<PQNIST_SEED_LENGTH; i++) seed[i]=i+1;
+    printf("SEED: ");
+    amcl_print_hex(seed, PQNIST_SEED_LENGTH);
+    printf("\n");
+
+    // BLS keys
+    char ski[BGS_BLS381];
+    char sko[BGS_BLS381];
+    char skr[BGS_BLS381];
+    char pki[G2LEN];
+
+    // BLS signature
+    char sigi[SIGLEN];
+    char sigr[SIGLEN];
+
+    // Octets for testing
+    octet SKI = {BGS_BLS381, BGS_BLS381, ski};
+    octet SKR = {BGS_BLS381, BGS_BLS381, skr};
+    octet SIGI = {SIGLEN, SIGLEN, sigi};
+    octet SIGR = {SIGLEN, SIGLEN, sigr};
+
+    rc = pqnist_bls_keys(seed, pki, ski);
+    if (rc)
+    {
+        fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("pki: ");
+    amcl_print_hex(pki, G2LEN);
+    printf("ski: ");
+    amcl_print_hex(ski, BGS_BLS381);
+    printf("\n");
+
+    // Alice signs message
+    rc = pqnist_bls_sign(P.val, ski, sigi);
+    if(rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("sigi ");
+    amcl_print_hex(sigi, SIGLEN);
+    printf("\n");
+
+    // Bob verifies message
+    rc = pqnist_bls_verify(P.val, pki, sigi);
+    if (rc != BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_verify rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    // Secret shares
+    char x[BGS_BLS381*n];
+    char y[BGS_BLS381*n];
+
+    // Make shares of BLS secret key
+    rc = pqnist_bls_make_shares(k, n, seed, x, y, ski, sko);
+    if (rc!=BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_make_shares rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("ski: ");
+    amcl_print_hex(ski, BGS_BLS381);
+    printf("sko: ");
+    amcl_print_hex(sko, BGS_BLS381);
+    printf("\n");
+
+    for(int i=0; i<n; i++)
+    {
+        printf("x[%d] ", i);
+        amcl_print_hex(&x[i*BGS_BLS381], BGS_BLS381);
+        printf("y[%d] ", i);
+        amcl_print_hex(&y[i*BGS_BLS381], BGS_BLS381);
+        printf("\n");
+    }
+
+    // Recover BLS secret key
+    rc = pqnist_bls_recover_secret(k, x, y, skr);
+    if (rc!=BLS_OK)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_recover_secret rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+    printf("skr: ");
+    amcl_print_hex(skr, BGS_BLS381);
+    printf("\n");
+
+    rc = OCT_comp(&SKI,&SKR);
+    if(!rc)
+    {
+        fprintf(stderr, "FAILURE SKI != SKR rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+
+    // Generate public keys and signatures using shares
+    char sigs[(SIGLEN)*n];
+    for(int i=0; i<n; i++)
+    {
+        rc = pqnist_bls_sign(P.val, &y[BFS_BLS381*i], &sigs[(SIGLEN)*i]);
+        if(rc != BLS_OK)
+        {
+            fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
+            printf("FAILURE\n");
+            exit(EXIT_FAILURE);
+        }
+
+    }
+
+    for(int i=0; i<n; i++)
+    {
+        printf("sigs[%d] ", i);
+        amcl_print_hex(&sigs[i*(SIGLEN)], SIGLEN);
+        printf("\n");
+    }
+
+    // Recover BLS signature
+    pqnist_bls_recover_signature(k, x, sigs, sigr);
+
+    printf("sigr ");
+    amcl_print_hex(sigr, SIGLEN);
+    printf("\n");
+
+    rc = OCT_comp(&SIGI,&SIGR);
+    if(!rc)
+    {
+        fprintf(stderr, "FAILURE SIGI != SIGR rc: %d\n", rc);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("SUCCESS\n");
+    exit(EXIT_SUCCESS);
+}
diff --git a/libs/crypto/libpqnist/test/smoke/test_encap_decap.c 
b/libs/crypto/libpqnist/test/smoke/test_encap_decap.c
index 304572c..51ca608 100644
--- a/libs/crypto/libpqnist/test/smoke/test_encap_decap.c
+++ b/libs/crypto/libpqnist/test/smoke/test_encap_decap.c
@@ -29,7 +29,7 @@
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
 #include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define NTHREADS 8
 #define MAXSIZE 256
@@ -82,14 +82,10 @@ int main()
     uint8_t SIKEpk[NTHREADS][OQS_KEM_sike_p751_length_public_key];
     uint8_t SIKEsk[NTHREADS][OQS_KEM_sike_p751_length_secret_key];
 
-    // Alice's BLS keys (not used)
-    char BLSpk[NTHREADS][G2LEN];
-    char BLSsk[NTHREADS][BGS_BLS381];
-
     #pragma omp parallel for
     for(i=0; i<NTHREADS; i++)
     {
-        rc = pqnist_keys(seedkeys[i], SIKEpk[i], SIKEsk[i], BLSpk[i], 
BLSsk[i]);
+        rc = pqnist_sike_keys(seedkeys[i], SIKEpk[i], SIKEsk[i]);
         if (rc)
         {
             fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
diff --git a/libs/crypto/libpqnist/test/smoke/test_pqnist.c 
b/libs/crypto/libpqnist/test/smoke/test_pqnist.c
index 3b21ee9..69f1dae 100644
--- a/libs/crypto/libpqnist/test/smoke/test_pqnist.c
+++ b/libs/crypto/libpqnist/test/smoke/test_pqnist.c
@@ -28,7 +28,7 @@
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
 #include <oqs/oqs.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define G2LEN 4*BFS_BLS381
 #define SIGLEN BFS_BLS381+1
@@ -92,10 +92,18 @@ int main()
     char BLSsk[BGS_BLS381];
     char BLSpk[G2LEN];
 
-    rc = pqnist_keys(seed, SIKEpk, SIKEsk, BLSpk, BLSsk);
+    rc = pqnist_sike_keys(seed, SIKEpk, SIKEsk);
     if (rc)
     {
-        fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc);
+        fprintf(stderr, "FAILURE pqnist_sike_keys rc: %d\n", rc);
+        printf("FAILURE\n");
+        exit(EXIT_FAILURE);
+    }
+
+    rc = pqnist_bls_keys(seed, BLSpk, BLSsk);
+    if (rc)
+    {
+        fprintf(stderr, "FAILURE pqnist_bls_keys rc: %d\n", rc);
         printf("FAILURE\n");
         exit(EXIT_FAILURE);
     }
@@ -189,15 +197,15 @@ int main()
     // Sign message
 
     // Alice signs message
-    rc = pqnist_sign(P.val, BLSsk, S);
+    rc = pqnist_bls_sign(P.val, BLSsk, S);
     if(rc)
     {
-        fprintf(stderr, "FAILURE pqnist_sign rc: %d\n", rc);
+        fprintf(stderr, "FAILURE pqnist_bls_sign rc: %d\n", rc);
         exit(EXIT_FAILURE);
     }
 
     // Bob verifies message
-    rc = pqnist_verify(P.val, BLSpk, S);
+    rc = pqnist_bls_verify(P.val, BLSpk, S);
     if (rc)
     {
         fprintf(stderr, "FAILURE: verify failed!\n errorCode %d", rc);
diff --git a/libs/crypto/libpqnist/test/unit/test_aes_decrypt.c 
b/libs/crypto/libpqnist/test/unit/test_aes_decrypt.c
index 88a36b7..8f36a2f 100644
--- a/libs/crypto/libpqnist/test/unit/test_aes_decrypt.c
+++ b/libs/crypto/libpqnist/test/unit/test_aes_decrypt.c
@@ -47,7 +47,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define LINE_LEN 500
 //#define DEBUG
diff --git a/libs/crypto/libpqnist/test/unit/test_aes_encrypt.c 
b/libs/crypto/libpqnist/test/unit/test_aes_encrypt.c
index 5864590..1b1ae0e 100644
--- a/libs/crypto/libpqnist/test/unit/test_aes_encrypt.c
+++ b/libs/crypto/libpqnist/test/unit/test_aes_encrypt.c
@@ -47,7 +47,7 @@
 #include <string.h>
 #include <amcl/utils.h>
 #include <amcl/randapi.h>
-#include <pqnist/pqnist.h>
+#include <amcl/pqnist.h>
 
 #define LINE_LEN 500
 //#define DEBUG
diff --git a/libs/crypto/pqnist.go b/libs/crypto/pqnist.go
index 89657c6..551f31a 100644
--- a/libs/crypto/pqnist.go
+++ b/libs/crypto/pqnist.go
@@ -16,13 +16,13 @@
 // under the License.
 
 /*
-Package crypto - wrapper for encryption libraries required by encrypted 
envelope
+Package crypto - wrapper for encryption libraries required by service
 */
 package crypto
 
 /*
-#cgo CFLAGS: -O2
-#cgo LDFLAGS: -lpqnist -lamcl_bls_BLS381 -lamcl_pairing_BLS381 
-lamcl_curve_BLS381 -lamcl_core -loqs
+#cgo CFLAGS:  -O2 -I/amcl -I/usr/local/include/amcl
+#cgo LDFLAGS: -L. -lpqnist -lamcl_bls_BLS381 -lamcl_pairing_BLS381 
-lamcl_curve_BLS381 -lamcl_core -loqs
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,7 +30,7 @@ package crypto
 #include <amcl/randapi.h>
 #include <amcl/bls_BLS381.h>
 #include <oqs/oqs.h>
-#include <pqnist.h>
+#include <amcl/pqnist.h>
 */
 import "C"
 import "unsafe"
@@ -47,43 +47,235 @@ const oqsKemSikeP751LengthPublicKey int = 
int(C.OQS_KEM_sike_p751_length_public_
 const oqsKemSikeP751LengthSecretKey int = 
int(C.OQS_KEM_sike_p751_length_secret_key)
 const oqsKemSikeP751LengthCiphertext int = 
int(C.OQS_KEM_sike_p751_length_ciphertext)
 
-// BLS
-const bfsBls381 int = int(C.BFS_BLS381)
-const bgsBls381 int = int(C.BGS_BLS381)
-const g2Len int = 4 * bfsBls381
-const siglen int = bfsBls381 + 1
+// BFSBLS381 Field size
+const BFSBLS381 int = int(C.BFS_BLS381)
 
-/*Keys Generate SIKE and BLS keys
+// BGSBLS381 Group size
+const BGSBLS381 int = int(C.BGS_BLS381)
 
-Generate SIKE and BLS key public and private key pairs
+// G2Len G2 point size
+const G2Len int = 4 * BFSBLS381
 
-@param seed             seed value for CSPRNG
-@param sikePK           SIKE public key
-@param sikeSK           SIKE secret key
-@param blsPK            BLS public key
-@param blsSK            BLS secret key
+// SIGLen Signature length
+const SIGLen int = BFSBLS381 + 1
+
+/*BLSKeys Generate BLS keys
+
+Generate public and private key pair. If the seed value is nil then
+generate the public key using the input secret key.
+
+@param seed             seed value for CSPRNG.
+@param ski              input secret key
+@param pk               public key
+@param sko              output secret key
 @param rc               Return code. Zero for success or else an error code
 */
-func Keys(seed []byte) (rc int, sikePK []byte, sikeSK []byte, blsPK []byte, 
blsSK []byte) {
+func BLSKeys(seed []byte, ski []byte) (rc int, pk []byte, sko []byte) {
 
        // Allocate memory
-       psikePK := C.malloc(C.size_t(oqsKemSikeP751LengthPublicKey))
-       defer C.free(psikePK)
-       psikeSK := C.malloc(C.size_t(oqsKemSikeP751LengthSecretKey))
-       defer C.free(psikeSK)
-       pblsPK := C.malloc(C.size_t(g2Len))
-       defer C.free(pblsPK)
-       pblsSK := C.malloc(C.size_t(bgsBls381))
-       defer C.free(pblsSK)
+       ppk := C.malloc(C.size_t(G2Len))
+       defer C.free(ppk)
+       var sk []byte
+
+       if seed == nil {
+               rtn := C.pqnist_bls_keys(nil, (*C.char)(ppk), 
(*C.char)(unsafe.Pointer(&ski[0])))
+               rc = int(rtn)
+
+               pk = C.GoBytes(ppk, C.int(G2Len))
+               sk = ski
+
+       } else {
+               psk := C.malloc(C.size_t(BGSBLS381))
+               defer C.free(psk)
+
+               rtn := C.pqnist_bls_keys((*C.char)(unsafe.Pointer(&seed[0])), 
(*C.char)(ppk), (*C.char)(psk))
+               rc = int(rtn)
+
+               pk = C.GoBytes(ppk, C.int(G2Len))
+               sko = C.GoBytes(psk, C.int(BGSBLS381))
+               sk = sko
+       }
+       return rc, pk, sk
+}
+
+/*BLSSign Sign a message
+
+  The message is signed using the BLS algorithm
+
+  @param M            Message to be signed
+  @param sk           secret key
+  @param S            Signature
+  @param rc           Return code. Zero for success or else an error code
+*/
+func BLSSign(m []byte, sk []byte) (rc int, s []byte) {
+       // Allocate memory
+       pS := C.malloc(C.size_t(SIGLen))
+       defer C.free(pS)
+
+       rtn := C.pqnist_bls_sign(
+               (*C.char)(unsafe.Pointer(&m[0])),
+               (*C.char)(unsafe.Pointer(&sk[0])),
+               (*C.char)(pS))
 
-       rtn := C.pqnist_keys((*C.char)(unsafe.Pointer(&seed[0])), 
(*C.char)(psikePK), (*C.char)(psikeSK), (*C.char)(pblsPK), (*C.char)(pblsSK))
        rc = int(rtn)
 
-       sikePK = C.GoBytes(psikePK, C.int(oqsKemSikeP751LengthPublicKey))
-       sikeSK = C.GoBytes(psikeSK, C.int(oqsKemSikeP751LengthSecretKey))
-       blsPK = C.GoBytes(pblsPK, C.int(g2Len))
-       blsSK = C.GoBytes(pblsSK, C.int(bgsBls381))
-       return rc, sikePK, sikeSK, blsPK, blsSK
+       s = C.GoBytes(pS, C.int(SIGLen))
+
+       return rc, s
+}
+
+/*BLSVerify Verify a signature
+
+  Verify a signature using the BLS algorithm
+
+  @param M            Message that was signed
+  @param pk           public key
+  @param S            Signature
+  @param rc           Return code. Zero for success or else an error code
+*/
+func BLSVerify(m []byte, pk []byte, s []byte) (rc int) {
+
+       rtn := C.pqnist_bls_verify(
+               (*C.char)(unsafe.Pointer(&m[0])),
+               (*C.char)(unsafe.Pointer(&pk[0])),
+               (*C.char)(unsafe.Pointer(&s[0])))
+
+       rc = int(rtn)
+
+       return rc
+}
+
+/*BLSAddG1 Add two members from the group G1
+
+  Add two members from the group G1
+
+  @param R1           member of G1
+  @param R2           member of G1
+  @param R            member of G1. r = r1+r2
+  @param rc           Return code. Zero for success or else an error code
+*/
+func BLSAddG1(R1 []byte, R2 []byte) (rc int, R []byte) {
+
+       // Allocate memory
+       pR := C.malloc(C.size_t(SIGLen))
+       defer C.free(pR)
+
+       rtn := C.pqnist_bls_addg1(
+               (*C.char)(unsafe.Pointer(&R1[0])),
+               (*C.char)(unsafe.Pointer(&R2[0])),
+               (*C.char)(pR))
+
+       rc = int(rtn)
+
+       R = C.GoBytes(pR, C.int(SIGLen))
+
+       return rc, R
+}
+
+/*BLSAddG2 Add two members from the group G2
+
+  Add two members from the group G2
+
+  @param R1           member of G2
+  @param R2           member of G2
+  @param R            member of G2. r = r1+r2
+  @param rc           Return code. Zero for success or else an error code
+*/
+func BLSAddG2(R1 []byte, R2 []byte) (rc int, R []byte) {
+
+       // Allocate memory
+       pR := C.malloc(C.size_t(G2Len))
+       defer C.free(pR)
+
+       rtn := C.pqnist_bls_addg2(
+               (*C.char)(unsafe.Pointer(&R1[0])),
+               (*C.char)(unsafe.Pointer(&R2[0])),
+               (*C.char)(pR))
+
+       rc = int(rtn)
+
+       R = C.GoBytes(pR, C.int(G2Len))
+
+       return rc, R
+}
+
+/*BLSMakeShares Use Shamir's secret sharing to distribute BLS secret keys
+
+Use Shamir's secret sharing to distribute BLS secret keys
+
+@param  k       Threshold
+@param  n       Number of shares
+@param  seed    seed value for CSPRNG
+@param  ski     Secret key to be shared.
+@param  x       x values
+@param  y       y values. Valid BLS secret keys
+@param  rc      Zero for success or else an error code
+*/
+func BLSMakeShares(k int, n int, seed []byte, ski []byte) (rc int, x []byte, y 
[]byte, sko []byte) {
+
+       // Allocate memory
+       pX := C.malloc(C.size_t(BGSBLS381 * n))
+       defer C.free(pX)
+       pY := C.malloc(C.size_t(BGSBLS381 * n))
+       defer C.free(pY)
+       pSKO := C.malloc(C.size_t(BGSBLS381))
+       defer C.free(pSKO)
+
+       rtn := C.pqnist_bls_make_shares(C.int(k), C.int(n), 
(*C.char)(unsafe.Pointer(&seed[0])), (*C.char)(pX), (*C.char)(pY), 
(*C.char)(unsafe.Pointer(&ski[0])), (*C.char)(pSKO))
+       rc = int(rtn)
+
+       sko = C.GoBytes(pSKO, C.int(BGSBLS381))
+       x = C.GoBytes(pX, C.int(BGSBLS381*n))
+       y = C.GoBytes(pY, C.int(BGSBLS381*n))
+       return rc, x, y, sko
+}
+
+/*BLSRecoverSecret Use Shamir's secret sharing to recover a BLS secret key
+
+Use Shamir's secret sharing to recover a BLS secret key
+
+@param  k       Threshold
+@param  x       x values
+@param  y       y values. Valid BLS secret keys
+@param  sk      Secret key that is recovered
+@param  rc      Zero for success or else an error code
+*/
+func BLSRecoverSecret(k int, x []byte, y []byte) (rc int, sk []byte) {
+
+       // Allocate memory
+       pSK := C.malloc(C.size_t(BGSBLS381))
+       defer C.free(pSK)
+
+       rtn := C.pqnist_bls_recover_secret(C.int(k), 
(*C.char)(unsafe.Pointer(&x[0])), (*C.char)(unsafe.Pointer(&y[0])), 
(*C.char)(pSK))
+       rc = int(rtn)
+
+       sk = C.GoBytes(pSK, C.int(BGSBLS381))
+
+       return rc, sk
+}
+
+/*BLSRecoverSignature Use Shamir's secret sharing to recover a BLS signature
+
+Use Shamir's secret sharing to recover a BLS signature
+
+@param  k       Threshold
+@param  x       x values
+@param  y       y values. Valid BLS signatures
+@param  sig     Signature that is recovered
+@param  rc      Zero for success or else an error code
+*/
+func BLSRecoverSignature(k int, x []byte, y []byte) (rc int, sig []byte) {
+
+       // Allocate memory
+       pSIG := C.malloc(C.size_t(SIGLen))
+       defer C.free(pSIG)
+
+       rtn := C.pqnist_bls_recover_signature(C.int(k), 
(*C.char)(unsafe.Pointer(&x[0])), (*C.char)(unsafe.Pointer(&y[0])), 
(*C.char)(pSIG))
+       rc = int(rtn)
+
+       sig = C.GoBytes(pSIG, C.int(SIGLen))
+
+       return rc, sig
 }
 
 /*AESCBCEncrypt AES-CBC Encryption
@@ -127,12 +319,37 @@ func AESCBCDecrypt(k []byte, iv []byte, c []byte) (p 
[]byte) {
        return c
 }
 
-/*EncapsulateEncrypt Encrypt a message and encapsulate the AES Key for
-  a recipient.
+/*SIKEKeys Generate SIKE keys
+
+Generate SIKE public and private key pair
+
+@param seed             seed value for CSPRNG
+@param sikePK           SIKE public key
+@param sikeSK           SIKE secret key
+@param rc               Return code. Zero for success or else an error code
+*/
+func SIKEKeys(seed []byte) (rc int, sikePK []byte, sikeSK []byte) {
+
+       // Allocate memory
+       psikePK := C.malloc(C.size_t(oqsKemSikeP751LengthPublicKey))
+       defer C.free(psikePK)
+       psikeSK := C.malloc(C.size_t(oqsKemSikeP751LengthSecretKey))
+       defer C.free(psikeSK)
+
+       rtn := C.pqnist_sike_keys((*C.char)(unsafe.Pointer(&seed[0])), 
(*C.char)(psikePK), (*C.char)(psikeSK))
+       rc = int(rtn)
+
+       sikePK = C.GoBytes(psikePK, C.int(oqsKemSikeP751LengthPublicKey))
+       sikeSK = C.GoBytes(psikeSK, C.int(oqsKemSikeP751LengthSecretKey))
+       return rc, sikePK, sikeSK
+}
+
+/*EncapsulateEncrypt Encrypt a message and encapsulate the AES Key for a 
recipient.
 
   The  message is encrypted using AES-256. The key
   is generated inside this function as an output
-  from the encapsulation function.
+  from the encapsulation function. The ciphertext
+  is returned using the P paramter.
 
   @param P            Plaintext to be encrypted
   @param IV           Initialization vector IV (16 bytes)
@@ -141,9 +358,7 @@ func AESCBCDecrypt(k []byte, iv []byte, c []byte) (p 
[]byte) {
   @param EK           Encapsulated key
   @param rc           Return code. Zero for success or else an error code
 */
-func EncapsulateEncrypt(pOrig []byte, iv []byte, sikePK []byte) (rc int, c 
[]byte, ek []byte) {
-       p := make([]byte, len(pOrig))
-       _ = copy(p, pOrig)
+func EncapsulateEncrypt(p []byte, iv []byte, sikePK []byte) (rc int, c []byte, 
ek []byte) {
 
        // Allocate memory
        pEK := C.malloc(C.size_t(oqsKemSikeP751LengthCiphertext))
@@ -162,10 +377,11 @@ func EncapsulateEncrypt(pOrig []byte, iv []byte, sikePK 
[]byte) (rc int, c []byt
        return rc, p, ek
 }
 
-/*DecapsulateDecrypt  @brief Decapsulate the AES Key and decrypt the message
+/*DecapsulateDecrypt Decapsulate the AES Key and decrypt the message
 
 Decapsulate the AES key and use it to decrypt the
-ciphertext.
+ciphertext. The plaintext is returned using the C
+parameter.
 
 @param C            Ciphertext to be decrypted
 @param IV           Initialization vector IV
@@ -174,10 +390,7 @@ ciphertext.
 @param P            Plaintext
 @param rc           Return code. Zero for success or else an error code
 */
-func DecapsulateDecrypt(cOrig []byte, iv []byte, sikeSK []byte, ek []byte) (rc 
int, p []byte) {
-
-       c := make([]byte, len(cOrig))
-       _ = copy(c, cOrig)
+func DecapsulateDecrypt(c []byte, iv []byte, sikeSK []byte, ek []byte) (rc 
int, p []byte) {
 
        rtn := C.pqnist_decapsulate_decrypt(
                (*C.char)(unsafe.Pointer(&c[0])),
@@ -189,50 +402,3 @@ func DecapsulateDecrypt(cOrig []byte, iv []byte, sikeSK 
[]byte, ek []byte) (rc i
 
        return rc, c
 }
-
-/*Sign a message
-
-  The message is signed using the BLS algorithm
-
-  @param M            Message to be signed
-  @param blsSK        BLS secret key
-  @param S            Signature
-  @param rc           Return code. Zero for success or else an error code
-*/
-func Sign(m []byte, blsSK []byte) (rc int, s []byte) {
-       // Allocate memory
-       pS := C.malloc(C.size_t(siglen))
-       defer C.free(pS)
-
-       rtn := C.pqnist_sign(
-               (*C.char)(unsafe.Pointer(&m[0])),
-               (*C.char)(unsafe.Pointer(&blsSK[0])),
-               (*C.char)(pS))
-
-       rc = int(rtn)
-
-       s = C.GoBytes(pS, C.int(siglen))
-
-       return rc, s
-}
-
-/*Verify a signature
-
-  Verify a signature using the BLS algorithm
-
-  @param M            Message that was signed
-  @param blsPK        BLS public key
-  @param S            Signature
-  @param rc           Return code. Zero for success or else an error code
-*/
-func Verify(m []byte, blsPK []byte, s []byte) (rc int) {
-
-       rtn := C.pqnist_verify(
-               (*C.char)(unsafe.Pointer(&m[0])),
-               (*C.char)(unsafe.Pointer(&blsPK[0])),
-               (*C.char)(unsafe.Pointer(&s[0])))
-
-       rc = int(rtn)
-
-       return rc
-}
diff --git a/libs/crypto/pqnist_test.go b/libs/crypto/pqnist_test.go
index 1b8a74a..dfa3232 100644
--- a/libs/crypto/pqnist_test.go
+++ b/libs/crypto/pqnist_test.go
@@ -54,11 +54,18 @@ func Test_Mine(t *testing.T) {
        SEEDHex := 
"2c82c5a6b14f6ce0fca9b83e929f6ca091fb25b6648676b3c387e8a13b0f4cee92a54d42e388db3fbb0e906b32e880f4"
        SEED, _ := hex.DecodeString(SEEDHex)
 
-       // Generate keys
-       RC1, SIKEpk, SIKEsk, BLSpk, BLSsk := Keys(SEED)
+       // Generate SIKE keys
+       RC1, SIKEpk, SIKEsk := SIKEKeys(SEED)
+       if RC1 != 0 {
+               fmt.Println("Panicking!")
+               panic("Failed to create SIKE keys")
+       }
+
+       // Generate BLS keys
+       RC1, BLSpk, BLSsk := BLSKeys(SEED, nil)
        if RC1 != 0 {
                fmt.Println("Panicking!")
-               panic("Failed to create keys")
+               panic("Failed to create BLS keys")
        }
 
        SIKEpkHex := hex.EncodeToString(SIKEpk)
@@ -103,11 +110,18 @@ func Test_Smoke_Test(t *testing.T) {
        // Messsage to encrypt and sign. Note it is zero padded.
        PHex := 
"48656c6c6f20426f622120546869732069732061206d6573736167652066726f6d20416c696365000000000000000000"
 
-       // Generate keys
-       RC1, SIKEpk, SIKEsk, BLSpk, BLSsk := Keys(SEED)
+       // Generate SIKE keys
+       RC1, SIKEpk, SIKEsk := SIKEKeys(SEED)
        if RC1 != 0 {
                fmt.Println("Panicking!")
-               panic("Failed to create keys")
+               panic("Failed to create SIKE keys")
+       }
+
+       // Generate BLS keys
+       RC1, BLSpk, BLSsk := BLSKeys(SEED, nil)
+       if RC1 != 0 {
+               fmt.Println("Panicking!")
+               panic("Failed to create BLS keys")
        }
 
        SIKEpkHex := hex.EncodeToString(SIKEpk)
@@ -162,8 +176,8 @@ func Test_Smoke_Test(t *testing.T) {
        P4 := AESCBCDecrypt(K2, IV1, C1)
        fmt.Printf("P4 : %s \n", P4)
 
-       // Sign a message
-       RC5, S := Sign(P1, BLSsk)
+       // BLS Sign a message
+       RC5, S := BLSSign(P1, BLSsk)
        if RC5 != 0 {
                fmt.Println("Panicking!")
                panic("Failed to sign message")
@@ -171,8 +185,8 @@ func Test_Smoke_Test(t *testing.T) {
        SHex := hex.EncodeToString(S)
        fmt.Printf("S : %s \n", SHex)
 
-       // Verify signature
-       RC6 := Verify(P1, BLSpk, S)
+       // BLS Verify signature
+       RC6 := BLSVerify(P1, BLSpk, S)
        if RC6 != 0 {
                fmt.Println("Panicking!")
                panic("Failed to verify signature")
@@ -222,7 +236,7 @@ func TestENCAP_DECAP(t *testing.T) {
        SEEDHex := 
"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30"
        SEED, _ := hex.DecodeString(SEEDHex)
 
-       RC1, SIKEpk, SIKEsk, _, _ := Keys(SEED)
+       RC1, SIKEpk, SIKEsk := SIKEKeys(SEED)
        assert.Equal(t, 0, RC1, "Should be equal")
 
        SIKEpkHex := hex.EncodeToString(SIKEpk)
@@ -251,28 +265,167 @@ func TestENCAP_DECAP(t *testing.T) {
        assert.Equal(t, want, got, "Should be equal")
 }
 
-func TestSIGN_VERIFY(t *testing.T) {
-       SEEDHex := 
"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
-       SEED, _ := hex.DecodeString(SEEDHex)
+func TestBLS(t *testing.T) {
+       seedHex := 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150"
+       seed, _ := hex.DecodeString(seedHex)
 
-       RC1, _, _, BLSpk, BLSsk := Keys(SEED)
-       assert.Equal(t, 0, RC1, "Should be equal")
+        messageStr := "test message"
+       message := []byte(messageStr)
 
-       BLSpkHex := hex.EncodeToString(BLSpk)
-       BLSskHex := hex.EncodeToString(BLSsk)
-       fmt.Printf("BLSpk : %s \n", BLSpkHex)
-       fmt.Printf("BLSsk : %s \n", BLSskHex)
+       RC1, pk1, sk1 := BLSKeys(seed, nil)
+       assert.Equal(t, 0, RC1, "Should be equal")
 
-       PHex := 
"48656c6c6f20426f622120546869732069732061206d6573736167652066726f6d20416c696365"
-       P, _ := hex.DecodeString(PHex)
+       pk1Hex := hex.EncodeToString(pk1)
+       sk1Hex := hex.EncodeToString(sk1)
+       fmt.Printf("pk1: %s \n", pk1Hex)
+       fmt.Printf("sk1: %s \n", sk1Hex)
 
-       RC2, S := Sign(P, BLSsk)
+       RC2, sig1 := BLSSign(message, sk1)
        assert.Equal(t, 0, RC2, "Should be equal")
-       // SHex := hex.EncodeToString(S)
-       // fmt.Printf("S : %s \n", SHex)
+
+        sig1Hex := hex.EncodeToString(sig1)
+       fmt.Printf("sig1: %s \n", sig1Hex)
 
        want := 0
-       got := Verify(P, BLSpk, S)
+       got := BLSVerify(message, pk1, sig1)
 
        assert.Equal(t, want, got, "Should be equal")
 }
+
+func TestBLSADD(t *testing.T) {
+       seed1Hex := 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150"
+       seed2Hex := 
"46389f32b7cdebbbc46b7165d8fae888c9de444898390a939977e1a066256a6f465e7d76307178aef81ae0c6841f9b7c"
+       seed1, _ := hex.DecodeString(seed1Hex)
+       seed2, _ := hex.DecodeString(seed2Hex)  
+
+        messageStr := "test message"
+       message := []byte(messageStr)
+
+        pk12GoldenHex := 
"0fff41dc3b28fee38f564158f9e391a5c6ac42179fcccdf5ee4513030b6d59900a832f9a886b2407dc8b0a3b51921326123d3974bd1864fb22f5a84e83f1f9f611ee082ed5bd6ca896d464f12907ba8acdf15c44f9cff2a2dbb3b32259a1fe4f11d470158066087363df20a11144d6521cf72dca1a7514154a95c7fe73b219989cc40d7fc7e0b97854fc3123c0cf50ae0452730996a5cb24641aff7102fcbb2af705d0f32d5787ca1c3654e4ae6aa59106e1e22e29018ba7c341f1e6472f800f"
+        sig12GoldenHex := 
"0203799dc2941b810985d9eb694a5be4a1ad5817f9e5d7c31870bb9fb471f7353eafacdc548544f9e7b78a0a9372c63ab0"
+       pk12Golden, _ := hex.DecodeString(pk12GoldenHex)
+       sig12Golden, _ := hex.DecodeString(sig12GoldenHex)      
+
+       RC1, pktmp, sktmp := BLSKeys(seed1, nil)
+       assert.Equal(t, 0, RC1, "Should be equal")
+
+       RC1, pk1, sk1 := BLSKeys(nil, sktmp)
+       assert.Equal(t, 0, RC1, "Should be equal")
+
+       assert.Equal(t, pktmp, pk1, "Should be equal")
+       assert.Equal(t, sktmp, sk1, "Should be equal")  
+
+       RC2, pk2, sk2 := BLSKeys(seed2, nil)
+       assert.Equal(t, 0, RC2, "Should be equal")      
+
+       RC3, sig1 := BLSSign(message, sk1)
+       assert.Equal(t, 0, RC3, "Should be equal")
+
+       RC4, sig2 := BLSSign(message, sk2)
+       assert.Equal(t, 0, RC4, "Should be equal")
+
+       RC5 := BLSVerify(message, pk1, sig1)
+       assert.Equal(t, 0, RC5, "Should be equal")
+       
+       RC6 := BLSVerify(message, pk2, sig2)
+       assert.Equal(t, 0, RC6, "Should be equal")
+
+       RC7, sig12 := BLSAddG1(sig1, sig2)
+       assert.Equal(t, 0, RC7, "Should be equal")
+
+       RC8, pk12 := BLSAddG2(pk1, pk2)
+       assert.Equal(t, 0, RC8, "Should be equal")
+
+       RC9 := BLSVerify(message, pk12, sig12)
+       assert.Equal(t, 0, RC9, "Should be equal")
+       
+       pk12Hex := hex.EncodeToString(pk12)
+       fmt.Printf("pk12Hex: %s \n", pk12Hex)
+       fmt.Printf("pk12GoldenHex: %s \n", pk12GoldenHex)
+
+       sig12Hex := hex.EncodeToString(sig12)
+       fmt.Printf("sig12Hex: %s \n", sig12Hex)
+       fmt.Printf("sig12GoldenHex: %s \n", sig12GoldenHex)
+
+       assert.Equal(t, pk12, pk12Golden, "Should be equal")
+       assert.Equal(t, sig12, sig12Golden, "Should be equal")  
+}
+
+func TestBLSSSS(t *testing.T) {
+       seed1Hex := 
"3370f613c4fe81130b846483c99c032c17dcc1904806cc719ed824351c87b0485c05089aa34ba1e1c6bfb6d72269b150"
+       seed2Hex := 
"46389f32b7cdebbbc46b7165d8fae888c9de444898390a939977e1a066256a6f465e7d76307178aef81ae0c6841f9b7c"
+       seed1, _ := hex.DecodeString(seed1Hex)
+       seed2, _ := hex.DecodeString(seed2Hex)  
+
+        messageStr := "test message"
+       message := []byte(messageStr)
+
+        const k int = 3
+       const n int = 4
+
+        sigGoldenHex := 
"03108b67f20b138e3080208efae105e31868ac34212bf03d80050d01de13a2c52b8bc3eafa3589045aebf11ec00dcf91f3
 "
+        xGoldenHex := 
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"
+        yGoldenHex := 
"0000000000000000000000000000000069f67565fd82de218a8b743b5516f948a72500ac3beb3ba072908cad2a146a91000000000000000000000000000000005f6f919d81a63fd53406794ae714b95a705c51de8001ef16f3f869dc515dcb3d000000000000000000000000000000005ce9d01ed92320a6d7aa195ca74db9735cdbe1ed55a3d026b4736792ee08852500000000000000000000000000000000626530ea03f980967576547095c1f9936ca3b0d8bcd0decfb40185d100149849"
+        ysigsGoldenHex := 
"0202982b889c082f159a7d8720d8d33a42005f13af0906763383fdce13607d9c0a2672f04c4600b36dd8a7f272c03908760210c06e79b26ee842c31d4ff8ce68d30da4247c7ab1c6162c011dada87b211f7172628ef78a39e61549c9f7b05245a7010316518c690e15de48fdb512bd47180925da7b3320bc52bdb5a239fad77cb975ede4aea20bef0bd570c50dc27240864564030ad08e4a60a0f330588f60f0a6535e79a99dd3c74af22f7b1137a01db65c95bd100745a2c0d5968e1a8ea5b4f3ce3736"
+       sigGolden, _ := hex.DecodeString(sigGoldenHex)
+       xGolden, _ := hex.DecodeString(xGoldenHex)
+       yGolden, _ := hex.DecodeString(yGoldenHex)
+       ysigsGolden, _ := hex.DecodeString(ysigsGoldenHex)                      
+
+       RC1, pki, ski := BLSKeys(seed1, nil)
+       assert.Equal(t, 0, RC1, "Should be equal")
+
+       RC2, sigi := BLSSign(message, ski)
+       assert.Equal(t, 0, RC2, "Should be equal")
+
+       RC3 := BLSVerify(message, pki, sigi)
+       assert.Equal(t, 0, RC3, "Should be equal")
+
+        // y is an array of BLS secret keys
+        RC4, x, y, sko := BLSMakeShares(k, n, seed2, ski)
+       assert.Equal(t, 0, RC4, "Should be equal")
+
+       assert.Equal(t, ski, sko, "Should be equal")
+       
+       xHex := hex.EncodeToString(x)
+       fmt.Printf("xHex: %s \n", xHex)
+       fmt.Printf("xGoldenHex: %s \n", xGoldenHex)
+
+       yHex := hex.EncodeToString(y)
+       fmt.Printf("yHex: %s \n", yHex)
+       fmt.Printf("yGoldenHex: %s \n", yGoldenHex)
+
+       assert.Equal(t, x, xGolden, "Should be equal")
+       assert.Equal(t, y, yGolden, "Should be equal")
+
+        var ys [n][]byte
+       for i := 0;  i<n; i++ {
+               ys[i] = y[(i*BGSBLS381):((i+1)*BGSBLS381)]
+                ysHex := hex.EncodeToString(ys[i])
+               fmt.Printf("ys[%d]: %s \n", i, ysHex)
+       }
+
+        // Generate signatures from shares
+       var sigs [n][]byte
+       var RC5 int
+       var ysigs []byte        
+       for i := 0;  i<n; i++ {
+               RC5, sigs[i] = BLSSign(message, ys[i])
+               assert.Equal(t, 0, RC5, "Should be equal")
+                sigsHex := hex.EncodeToString(sigs[i])
+               fmt.Printf("sigs[%d]: %s \n", i, sigsHex)
+               ysigs = append(ysigs, sigs[i]...)
+       }
+        ysigsHex := hex.EncodeToString(ysigs)
+        fmt.Printf("ysigs %s \n", ysigsHex)
+
+       assert.Equal(t, ysigs, ysigsGolden, "Should be equal")
+       
+        RC7, sigr := BLSRecoverSignature(k, x, ysigs)
+       assert.Equal(t, 0, RC7, "Should be equal")
+       
+       sigrHex := hex.EncodeToString(sigr)
+       fmt.Printf("sigr: %s \n", sigrHex)
+
+       assert.Equal(t, sigr, sigGolden, "Should be equal")
+}
diff --git a/libs/documents/crypto.go b/libs/documents/crypto.go
index aac9b81..f504ec0 100644
--- a/libs/documents/crypto.go
+++ b/libs/documents/crypto.go
@@ -112,7 +112,7 @@ func sign(envelope Envelope, blsSK []byte, signerNodeID 
string) (SignedEnvelope,
        if err != nil {
                return SignedEnvelope{}, errors.Wrap(err, "Failed to serialize 
envelope in SignBLS")
        }
-       rc, signature := crypto.Sign(envelopeBytes, blsSK)
+       rc, signature := crypto.BLSSign(envelopeBytes, blsSK)
        if rc != 0 {
                return SignedEnvelope{}, errors.Wrap(err, "Failed to sign 
envelope in in SignBLS")
        }
@@ -128,7 +128,7 @@ func Verify(signedEnvelope SignedEnvelope, blsPK []byte) 
error {
        message := signedEnvelope.Message
        signature := signedEnvelope.Signature
 
-       rc := crypto.Verify(message, blsPK, signature)
+       rc := crypto.BLSVerify(message, blsPK, signature)
        if rc == 0 {
                return nil
        }
diff --git a/libs/documents/docs_test.go b/libs/documents/docs_test.go
index 62f66d8..3ff5099 100644
--- a/libs/documents/docs_test.go
+++ b/libs/documents/docs_test.go
@@ -117,7 +117,7 @@ func Test_EncodeDecode(t *testing.T) {
        }
        seed, _ := cryptowallet.RandomBytes(16)
        //Now generate a test Document & use some temp keys, as once made, we 
needs the TestID above to decode
-       _, _, _, blsPK, blsSK := crypto.Keys(seed)
+       blsPK, blsSK := crypto.BLSKeys(seed, nil)
        secretBody := &SimpleString{Content: "B"}
        plainText := &SimpleString{Content: "A"}
        header := &Header{}
@@ -184,7 +184,13 @@ func BuildTestOrderDoc() (OrderDoc, error) {
 func BuildTestIDDoc() (IDDoc, string, []byte, []byte, []byte, []byte) {
        //make some test ID docs
        seed, _ := cryptowallet.RandomBytes(16)
-       _, sikePK, sikeSK, blsPK, blsSK := crypto.Keys(seed)
+
+        RC1, sikePK, sikeSK := crypto.SIKEKeys(seed)
+       assert.Equal(t, 0, RC1, "Should be equal")
+
+       RC2, blsPK, blsSK := crypto.BLSKeys(seed, nil)
+       assert.Equal(t, 0, RC2, "Should be equal")
+
        //id := []byte("TestID1")
        envelope := Envelope{}
        header := Header{}
diff --git a/pkg/defaultservice/identity.go b/pkg/defaultservice/identity.go
index 42f3445..9dfd5a0 100644
--- a/pkg/defaultservice/identity.go
+++ b/pkg/defaultservice/identity.go
@@ -38,15 +38,19 @@ func (s *Service) CreateIdentity(req 
*api.CreateIdentityRequest) (*api.CreateIde
        if err != nil {
                return nil, errors.Wrap(err, "Failed to Generate random seed")
        }
-       //Generate SIKE and BLS keys
-       rc, sikePublicKey, sikeSecretKey, blsPublicKey, blsSecretKey := 
crypto.Keys(seed)
 
-       if rc != 0 {
-               return nil, errors.New("Failed to generate SIKE and BLS keys")
+        //Generate SIKE keys
+       rc1, sikePublicKey, sikeSecretKey := crypto.SIKEKeys(seed)
+       if rc1 != 0 {
+               return nil, errors.New("Failed to generate SIKE keys")
        }
-       if err != nil {
-               return nil, errors.Wrap(err, "Failed to Initialise Beneficary 
in Cryptowallet Library")
+
+        //Generate BLS keys
+       rc1, blsPublicKey, blsSecretKey := crypto.BLSKeys(seed, nil)
+       if rc1 != 0 {
+               return nil, errors.New("Failed to generate BLS keys")
        }
+
        ecPubKey, err := common.InitECKeys(seed)
        if err != nil {
                return nil, errors.Wrap(err, "Failed to Generate EC Pub Key 
from random seed")

Reply via email to