Merge pull request #25 from apache/issue15

externally generated BLS secret key
diff --git a/VERSION b/VERSION
index 3eefcb9..9084fa2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
+1.1.0
diff --git a/examples/node/example_BLS_BLS381.js b/examples/node/example_BLS_BLS381.js
index f7f2c77..0c39344 100644
--- a/examples/node/example_BLS_BLS381.js
+++ b/examples/node/example_BLS_BLS381.js
@@ -42,10 +42,15 @@
 
 // User 1
 var sk1=[];
+var pktmp=[];
 var pk1=[];
 var sig1=[];
 
-ctx.BLS.KeyPairGenerate(rng,sk1,pk1);
+ctx.BLS.KeyPairGenerate(rng,sk1,pktmp);
+console.log("Private key user 1: 0x"+ctx.BLS.bytestostring(sk1));
+console.log("Public key user 1: 0x"+ctx.BLS.bytestostring(pktmp));
+
+ctx.BLS.KeyPairGenerate(null,sk1,pk1);
 console.log("Private key user 1: 0x"+ctx.BLS.bytestostring(sk1));
 console.log("Public key user 1: 0x"+ctx.BLS.bytestostring(pk1));
 
diff --git a/src/bls.js b/src/bls.js
index 468f94a..65ba8ae 100644
--- a/src/bls.js
+++ b/src/bls.js
@@ -1,3 +1,4 @@
+// This is just a sample script. Paste your real code (javascript or HTML) here.
 /*
     Licensed to the Apache Software Foundation (ASF) under one
     or more contributor license agreements.  See the NOTICE file
@@ -18,7 +19,6 @@
 */
 
 /* BLS API Functions */
-
 var BLS = function(ctx) {
     "use strict";
 
@@ -27,7 +27,7 @@
      *
      * @constructor
      * @this {BLS}
-     */        
+     */
     var BLS = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -35,13 +35,13 @@
         BFS: ctx.BIG.MODBYTES,
         BGS: ctx.BIG.MODBYTES,
 
-       /**
+        /**
          * Convert byte array to string
          *
          * @this {BLS}
          * @parameter b byte array
          * @return string
-         */		
+         */
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -57,13 +57,13 @@
             return s;
         },
 
-       /**
+        /**
          * Convert string to byte array 
          *
          * @this {BLS}
          * @parameter s string
          * @return byte array
-         */			
+         */
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -77,144 +77,152 @@
 
 
         /**
-          *  hash a message to an ECP point, using SHA3 
-          *
-          * @this {BLS}
-          * @parameter m message to be hashedstring
-          * @return ECP point
-          */	
+         *  hash a message to an ECP point, using SHA3 
+         *
+         * @this {BLS}
+         * @parameter m message to be hashedstring
+         * @return ECP point
+         */
         bls_hashit: function(m) {
-			var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+            var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
             var hm = [];
-            var t=this.stringtobytes(m);
-			for (var i=0;i<t.length;i++)
-				sh.process(t[i]);
-			sh.shake(hm,this.BFS);
-			var P=ctx.ECP.mapit(hm);
-			return P;
-		},
+            var t = this.stringtobytes(m);
+            for (var i = 0; i < t.length; i++)
+                sh.process(t[i]);
+            sh.shake(hm, this.BFS);
+            var P = ctx.ECP.mapit(hm);
+            return P;
+        },
 
-	/**
-          * Generate key pair
-          *
-          * @this {BLS}
-          * @parameter rng Cryptographically Secure Random Number Generator
-          * @parameter S Private key
-          * @parameter W Public key
-          * @return Error code
-          */	
-	KeyPairGenerate(rng,S,W) {
-			var G=ctx.ECP2.generator();
-			var q=new ctx.BIG(0);
-			q.rcopy(ctx.ROM_CURVE.CURVE_Order);
-			var s=ctx.BIG.randomnum(q,rng);
-            s.toBytes(S);
-            G = ctx.PAIR.G2mul(G,s);
+        /**
+         * Generate key pair
+         *
+         * @this {BLS}
+         * @parameter rng Cryptographically Secure Random Number Generator
+         * @parameter S Private key. Generated externally if RNG set to NULL
+         * @parameter W Public key
+         * @return Error code
+         */
+        KeyPairGenerate(rng, S, W) {
+            var G = ctx.ECP2.generator();
+	    var s;
+	    
+            var q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
 
-            G.toBytes(W);  // To use point compression on public keys, change to true 
-			return this.BLS_OK;
-		},
+            if (rng != null) {
+                s = ctx.BIG.randomnum(q, rng);
+                s.toBytes(S);
+            } else {
+                s = ctx.BIG.fromBytes(S);
+            }
+	    
+            G = ctx.PAIR.G2mul(G, s);
+            G.toBytes(W);
+	    
+            return this.BLS_OK;
+        },
 
-	/**
-          * Sign message
-          *
-          * @this {BLS}
-          * @parameter SIG Singature
-          * @parameter m Message to sign
-          * @parameter S Private key
-          * @return Error code
-          */		
-	sign(SIG,m,S) {
-			var D=this.bls_hashit(m);
-			var s=ctx.BIG.fromBytes(S);
-			D=ctx.PAIR.G1mul(D,s);
-			D.toBytes(SIG,true);
-			return this.BLS_OK;
-		},
+        /**
+         * Sign message
+         *
+         * @this {BLS}
+         * @parameter SIG Singature
+         * @parameter m Message to sign
+         * @parameter S Private key
+         * @return Error code
+         */
+        sign(SIG, m, S) {
+            var D = this.bls_hashit(m);
+            var s = ctx.BIG.fromBytes(S);
+            D = ctx.PAIR.G1mul(D, s);
+            D.toBytes(SIG, true);
+            return this.BLS_OK;
+        },
 
-	/**
-          * Verify message
-          *
-          * @this {BLS}
-          * @parameter SIG Signature
-          * @parameter m Message to sign
-          * @parameter W Public key
-          * @return Error code
-          */			
-	verify(SIG,m,W) {
-			var HM=this.bls_hashit(m);
-			var D=ctx.ECP.fromBytes(SIG);
-			var G=ctx.ECP2.generator();
-			var PK=ctx.ECP2.fromBytes(W);
-			D.neg();
+        /**
+         * Verify message
+         *
+         * @this {BLS}
+         * @parameter SIG Signature
+         * @parameter m Message to sign
+         * @parameter W Public key
+         * @return Error code
+         */
+        verify(SIG, m, W) {
+            var HM = this.bls_hashit(m);
+            var D = ctx.ECP.fromBytes(SIG);
+            var G = ctx.ECP2.generator();
+            var PK = ctx.ECP2.fromBytes(W);
+            D.neg();
 
-// Use new multi-pairing mechanism 
-			var r=ctx.PAIR.initmp();
-			ctx.PAIR.another(r,G,D);
-			ctx.PAIR.another(r,PK,HM);
-			var v=ctx.PAIR.miller(r);
+            // Use new multi-pairing mechanism 
+            var r = ctx.PAIR.initmp();
+            ctx.PAIR.another(r, G, D);
+            ctx.PAIR.another(r, PK, HM);
+            var v = ctx.PAIR.miller(r);
 
-//.. or alternatively
-//			var v=ctx.PAIR.ate2(G,D,PK,HM);
+            //.. or alternatively
+            //			var v=ctx.PAIR.ate2(G,D,PK,HM);
 
-			v=ctx.PAIR.fexp(v);
-			if (v.isunity())
-				return this.BLS_OK;
-			return this.BLS_FAIL;
-		},
+            v = ctx.PAIR.fexp(v);
+            if (v.isunity())
+                return this.BLS_OK;
+            return this.BLS_FAIL;
+        },
 
-	/**
-          * R=R1+R2 in group G1 
-          *
-          * @this {BLS}
-          * @parameter R1 G1 Point
-          * @parameter R2 G1 Point
-          * @parameter R G1 Point
-          * @return Error code
-          */			
+        /**
+         * R=R1+R2 in group G1 
+         *
+         * @this {BLS}
+         * @parameter R1 G1 Point
+         * @parameter R2 G1 Point
+         * @parameter R G1 Point
+         * @return Error code
+         */
         add_G1(R1, R2, R) {
-                       var P = ctx.ECP.fromBytes(R1),
-                       Q = ctx.ECP.fromBytes(R2);
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
 
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-		       }
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
 
-                       P.add(Q);
+            P.add(Q);
 
-                       P.toBytes(R,true);
+            P.toBytes(R, true);
 
-                       return 0;
-                },
+            return 0;
+        },
 
- 	/**
-          *  W=W1+W2 in group G2 
-          *
-          * @this {BLS}
-          * @parameter W1 G2 Point
-          * @parameter W2 G2 Point
-          * @parameter R G2 Point
-          * @return Error code
-          */			
+        /**
+         *  W=W1+W2 in group G2 
+         *
+         * @this {BLS}
+         * @parameter W1 G2 Point
+         * @parameter W2 G2 Point
+         * @parameter R G2 Point
+         * @return Error code
+         */
         add_G2(W1, W2, W) {
-                       var P = ctx.ECP2.fromBytes(W1),
-                       Q = ctx.ECP2.fromBytes(W2);
+            var P = ctx.ECP2.fromBytes(W1),
+                Q = ctx.ECP2.fromBytes(W2);
 
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-                       }
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
 
-                       P.add(Q);
+            P.add(Q);
 
-                       P.toBytes(W);
+            P.toBytes(W);
 
-                       return 0;
-                }
-	
+            return 0;
+        }
+
     };
 
     return BLS;
-};	
+};
 
 if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
     module.exports = {
diff --git a/src/bls192.js b/src/bls192.js
index 4c46501..236299b 100644
--- a/src/bls192.js
+++ b/src/bls192.js
@@ -18,16 +18,15 @@
 */
 
 /* BLS API Functions */
-
 var BLS192 = function(ctx) {
     "use strict";
-    
+
     /**
      * Creates an instance of BLS192
      *
      * @constructor
      * @this {BLS192}
-    */
+     */
     var BLS192 = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -35,7 +34,7 @@
         BFS: ctx.BIG.MODBYTES,
         BGS: ctx.BIG.MODBYTES,
 
-       /**
+        /**
          * Convert byte array to string
          *
          * @this {BLS192}
@@ -57,13 +56,13 @@
             return s;
         },
 
-       /**
+        /**
          * Convert string to byte array 
          *
          * @this {BLS192}
          * @parameter s string
          * @return byte array
-         */	
+         */
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -76,144 +75,152 @@
         },
 
         /**
-          *  hash a message to an ECP point, using SHA3 
-          *
-          * @this {BLS192}
-          * @parameter m message to be hashedstring
-          * @return ECP point
-          */	
+         *  hash a message to an ECP point, using SHA3 
+         *
+         * @this {BLS192}
+         * @parameter m message to be hashedstring
+         * @return ECP point
+         */
         bls_hashit: function(m) {
-			var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
-                        var hm = [];
-                        var t=this.stringtobytes(m);
-			for (var i=0;i<t.length;i++)
-				sh.process(t[i]);
-			sh.shake(hm,this.BFS);
-			var P=ctx.ECP.mapit(hm);
-			return P;
-		},
-
-	/**
-          * Generate key pair
-          *
-          * @this {BLS192}
-          * @parameter rng Cryptographically Secure Random Number Generator
-          * @parameter S Private key
-          * @parameter W Public key
-          * @return Error code
-          */	
-	KeyPairGenerate(rng,S,W) {
-	    var G=ctx.ECP4.generator();
-	    var q=new ctx.BIG(0);
-	    q.rcopy(ctx.ROM_CURVE.CURVE_Order);
-	    var s=ctx.BIG.randomnum(q,rng);
-            s.toBytes(S);
-            G = ctx.PAIR192.G2mul(G,s);
-            G.toBytes(W);  // To use point compression on public keys, change to true 
-			return this.BLS_OK;
-
-		},
-
-	/**
-          * Sign message
-          *
-          * @this {BLS192}
-          * @parameter SIG Singature
-          * @parameter m Message to sign
-          * @parameter S Private key
-          * @return Error code
-          */		
-	sign(SIG,m,S) {
-		var D=this.bls_hashit(m);
-		var s=ctx.BIG.fromBytes(S);
-		D=ctx.PAIR192.G1mul(D,s);
-
-	        D.toBytes(SIG,true);
-		return this.BLS_OK;
-	},
-
-	/**
-          * Verify message
-          *
-          * @this {BLS192}
-          * @parameter SIG Signature
-          * @parameter m Message to sign
-          * @parameter W Public key
-          * @return Error code
-          */			
-	verify(SIG,m,W) {
-			var HM=this.bls_hashit(m);
-			var D=ctx.ECP.fromBytes(SIG);
-			var G=ctx.ECP4.generator();
-			var PK=ctx.ECP4.fromBytes(W);
-			D.neg();
-
-// Use new multi-pairing mechanism 
-			var r=ctx.PAIR192.initmp();
-			ctx.PAIR192.another(r,G,D);
-			ctx.PAIR192.another(r,PK,HM);
-			var v=ctx.PAIR192.miller(r);
-
-//.. or alternatively
-//			var v=ctx.PAIR192.ate2(G,D,PK,HM);
-			v=ctx.PAIR192.fexp(v);
-			if (v.isunity())
-				return this.BLS_OK;
-			return this.BLS_FAIL;
-		},
-
-	/**
-          * R=R1+R2 in group G1 
-          *
-          * @this {BLS192}
-          * @parameter R1 G1 Point
-          * @parameter R2 G1 Point
-          * @parameter R G1 Point
-          * @return Error code
-          */			
-        add_G1(R1, R2, R) {
-                       var P = ctx.ECP.fromBytes(R1),
-                       Q = ctx.ECP.fromBytes(R2);
-
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-		       }
-
-                       P.add(Q);
-
-                       P.toBytes(R,true);
-
-                       return 0;
+            var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+            var hm = [];
+            var t = this.stringtobytes(m);
+            for (var i = 0; i < t.length; i++)
+                sh.process(t[i]);
+            sh.shake(hm, this.BFS);
+            var P = ctx.ECP.mapit(hm);
+            return P;
         },
 
-	/**
-          *  W=W1+W2 in group G2 
-          *
-          * @this {BLS192}
-          * @parameter W1 G2 Point
-          * @parameter W2 G2 Point
-          * @parameter R G2 Point
-          * @return Error code
-          */			
+        /**
+         * Generate key pair
+         *
+         * @this {BLS192}
+         * @parameter rng Cryptographically Secure Random Number Generator
+         * @parameter S Private key
+         * @parameter W Public key
+         * @return Error code
+         */
+        KeyPairGenerate(rng, S, W) {
+            var G = ctx.ECP4.generator();
+	    var s;
+	    
+            var q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
+
+            if (rng != null) {
+                s = ctx.BIG.randomnum(q, rng);
+                s.toBytes(S);
+            } else {
+                s = ctx.BIG.fromBytes(S);
+            }
+	    
+            G = ctx.PAIR192.G2mul(G, s);
+            G.toBytes(W);
+	    
+            return this.BLS_OK;
+        },
+
+        /**
+         * Sign message
+         *
+         * @this {BLS192}
+         * @parameter SIG Singature
+         * @parameter m Message to sign
+         * @parameter S Private key
+         * @return Error code
+         */
+        sign(SIG, m, S) {
+            var D = this.bls_hashit(m);
+            var s = ctx.BIG.fromBytes(S);
+            D = ctx.PAIR192.G1mul(D, s);
+
+            D.toBytes(SIG, true);
+            return this.BLS_OK;
+        },
+
+        /**
+         * Verify message
+         *
+         * @this {BLS192}
+         * @parameter SIG Signature
+         * @parameter m Message to sign
+         * @parameter W Public key
+         * @return Error code
+         */
+        verify(SIG, m, W) {
+            var HM = this.bls_hashit(m);
+            var D = ctx.ECP.fromBytes(SIG);
+            var G = ctx.ECP4.generator();
+            var PK = ctx.ECP4.fromBytes(W);
+            D.neg();
+
+            // Use new multi-pairing mechanism 
+            var r = ctx.PAIR192.initmp();
+            ctx.PAIR192.another(r, G, D);
+            ctx.PAIR192.another(r, PK, HM);
+            var v = ctx.PAIR192.miller(r);
+
+            //.. or alternatively
+            //			var v=ctx.PAIR192.ate2(G,D,PK,HM);
+            v = ctx.PAIR192.fexp(v);
+            if (v.isunity())
+                return this.BLS_OK;
+            return this.BLS_FAIL;
+        },
+
+        /**
+         * R=R1+R2 in group G1 
+         *
+         * @this {BLS192}
+         * @parameter R1 G1 Point
+         * @parameter R2 G1 Point
+         * @parameter R G1 Point
+         * @return Error code
+         */
+        add_G1(R1, R2, R) {
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
+
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
+
+            P.add(Q);
+
+            P.toBytes(R, true);
+
+            return 0;
+        },
+
+        /**
+         *  W=W1+W2 in group G2 
+         *
+         * @this {BLS192}
+         * @parameter W1 G2 Point
+         * @parameter W2 G2 Point
+         * @parameter R G2 Point
+         * @return Error code
+         */
         add_G2(W1, W2, W) {
-                       var P = ctx.ECP4.fromBytes(W1),
-                       Q = ctx.ECP4.fromBytes(W2);
+            var P = ctx.ECP4.fromBytes(W1),
+                Q = ctx.ECP4.fromBytes(W2);
 
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-                       }
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
 
-                       P.add(Q);
+            P.add(Q);
 
-                       P.toBytes(W);
+            P.toBytes(W);
 
-                       return 0;
-                }
-	
+            return 0;
+        }
+
     };
 
     return BLS192;
-};	
+};
 
 if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
     module.exports = {
diff --git a/src/bls256.js b/src/bls256.js
index 269765d..ee2bf35 100644
--- a/src/bls256.js
+++ b/src/bls256.js
@@ -18,7 +18,6 @@
 */
 
 /* BLS API Functions */
-
 var BLS256 = function(ctx) {
     "use strict";
 
@@ -27,7 +26,7 @@
      *
      * @constructor
      * @this {BLS256}
-     */    
+     */
     var BLS256 = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -35,13 +34,13 @@
         BFS: ctx.BIG.MODBYTES,
         BGS: ctx.BIG.MODBYTES,
 
-       /**
+        /**
          * Convert byte array to string
          *
          * @this {BLS192}
          * @parameter b byte array
          * @return string
-         */	
+         */
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -57,13 +56,13 @@
             return s;
         },
 
-       /**
+        /**
          * Convert string to byte array 
          *
          * @this {BLS192}
          * @parameter s string
          * @return byte array
-         */		
+         */
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -76,141 +75,149 @@
         },
 
         /**
-          *  hash a message to an ECP point, using SHA3 
-          *
-          * @this {BLS192}
-          * @parameter m message to be hashedstring
-          * @return ECP point
-          */	
+         *  hash a message to an ECP point, using SHA3 
+         *
+         * @this {BLS192}
+         * @parameter m message to be hashedstring
+         * @return ECP point
+         */
         bls_hashit: function(m) {
-			var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
+            var sh = new ctx.SHA3(ctx.SHA3.SHAKE256);
             var hm = [];
-            var t=this.stringtobytes(m);
-			for (var i=0;i<t.length;i++)
-				sh.process(t[i]);
-			sh.shake(hm,this.BFS);
-			var P=ctx.ECP.mapit(hm);
-			return P;
-		},
+            var t = this.stringtobytes(m);
+            for (var i = 0; i < t.length; i++)
+                sh.process(t[i]);
+            sh.shake(hm, this.BFS);
+            var P = ctx.ECP.mapit(hm);
+            return P;
+        },
 
-	/**
-          * Generate key pair
-          *
-          * @this {BLS192}
-          * @parameter rng Cryptographically Secure Random Number Generator
-          * @parameter S Private key
-          * @parameter W Public key
-          * @return Error code
-          */	
- 	KeyPairGenerate(rng,S,W) {
-			var G=ctx.ECP8.generator();
-			var q=new ctx.BIG(0);
-			q.rcopy(ctx.ROM_CURVE.CURVE_Order);
-			var s=ctx.BIG.randomnum(q,rng);
-            s.toBytes(S);
-            G = ctx.PAIR256.G2mul(G,s);
-            G.toBytes(W);  // To use point compression on public keys, change to true 
-			return this.BLS_OK;
+        /**
+         * Generate key pair
+         *
+         * @this {BLS192}
+         * @parameter rng Cryptographically Secure Random Number Generator
+         * @parameter S Private key
+         * @parameter W Public key
+         * @return Error code
+         */
+        KeyPairGenerate(rng, S, W) {
+            var G = ctx.ECP8.generator();
+	    var s;
+	    
+            var q = new ctx.BIG(0);
+            q.rcopy(ctx.ROM_CURVE.CURVE_Order);
 
-		},
+            if (rng != null) {
+                s = ctx.BIG.randomnum(q, rng);
+                s.toBytes(S);
+            } else {
+                s = ctx.BIG.fromBytes(S);
+            }
 
-	/**
-          * Sign message
-          *
-          * @this {BLS192}
-          * @parameter SIG Singature
-          * @parameter m Message to sign
-          * @parameter S Private key
-          * @return Error code
-          */		
-	sign(SIG,m,S) {
-			var D=this.bls_hashit(m);
-			var s=ctx.BIG.fromBytes(S);
-			D=ctx.PAIR256.G1mul(D,s);
-			D.toBytes(SIG,true);
-			return this.BLS_OK;
-		},
+            G = ctx.PAIR256.G2mul(G, s);
+            G.toBytes(W); 
 
-	/**
-          * Verify message
-          *
-          * @this {BLS192}
-          * @parameter SIG Signature
-          * @parameter m Message to sign
-          * @parameter W Public key
-          * @return Error code
-          */			
-	verify(SIG,m,W) {
-			var HM=this.bls_hashit(m);
-			var D=ctx.ECP.fromBytes(SIG);
-			var G=ctx.ECP8.generator();
-			var PK=ctx.ECP8.fromBytes(W);
-			D.neg();
+            return this.BLS_OK;
+        },
 
-// Use new multi-pairing mechanism 
-			var r=ctx.PAIR256.initmp();
-			ctx.PAIR256.another(r,G,D);
-			ctx.PAIR256.another(r,PK,HM);
-			var v=ctx.PAIR256.miller(r);
+        /**
+         * Sign message
+         *
+         * @this {BLS192}
+         * @parameter SIG Singature
+         * @parameter m Message to sign
+         * @parameter S Private key
+         * @return Error code
+         */
+        sign(SIG, m, S) {
+            var D = this.bls_hashit(m);
+            var s = ctx.BIG.fromBytes(S);
+            D = ctx.PAIR256.G1mul(D, s);
+            D.toBytes(SIG, true);
+            return this.BLS_OK;
+        },
 
-//.. or alternatively
-//			var v=ctx.PAIR256.ate2(G,D,PK,HM);
+        /**
+         * Verify message
+         *
+         * @this {BLS192}
+         * @parameter SIG Signature
+         * @parameter m Message to sign
+         * @parameter W Public key
+         * @return Error code
+         */
+        verify(SIG, m, W) {
+            var HM = this.bls_hashit(m);
+            var D = ctx.ECP.fromBytes(SIG);
+            var G = ctx.ECP8.generator();
+            var PK = ctx.ECP8.fromBytes(W);
+            D.neg();
 
-			v=ctx.PAIR256.fexp(v);
-			if (v.isunity())
-				return this.BLS_OK;
-			return this.BLS_FAIL;
-		},
+            // Use new multi-pairing mechanism 
+            var r = ctx.PAIR256.initmp();
+            ctx.PAIR256.another(r, G, D);
+            ctx.PAIR256.another(r, PK, HM);
+            var v = ctx.PAIR256.miller(r);
+
+            //.. or alternatively
+            //			var v=ctx.PAIR256.ate2(G,D,PK,HM);
+
+            v = ctx.PAIR256.fexp(v);
+            if (v.isunity())
+                return this.BLS_OK;
+            return this.BLS_FAIL;
+        },
 
 
-	/**
-          * R=R1+R2 in group G1 
-          *
-          * @this {BLS192}
-          * @parameter R1 G1 Point
-          * @parameter R2 G1 Point
-          * @parameter R G1 Point
-          * @return Error code
-          */			
+        /**
+         * R=R1+R2 in group G1 
+         *
+         * @this {BLS192}
+         * @parameter R1 G1 Point
+         * @parameter R2 G1 Point
+         * @parameter R G1 Point
+         * @return Error code
+         */
         add_G1(R1, R2, R) {
-                       var P = ctx.ECP.fromBytes(R1),
-                       Q = ctx.ECP.fromBytes(R2);
+            var P = ctx.ECP.fromBytes(R1),
+                Q = ctx.ECP.fromBytes(R2);
 
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-		       }
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
 
-                       P.add(Q);
+            P.add(Q);
 
-                       P.toBytes(R,true);
+            P.toBytes(R, true);
 
-                       return 0;
-                },
+            return 0;
+        },
 
-	/**
-          *  W=W1+W2 in group G2 
-          *
-          * @this {BLS192}
-          * @parameter W1 G2 Point
-          * @parameter W2 G2 Point
-          * @parameter R G2 Point
-          * @return Error code
-          */			
+        /**
+         *  W=W1+W2 in group G2 
+         *
+         * @this {BLS192}
+         * @parameter W1 G2 Point
+         * @parameter W2 G2 Point
+         * @parameter R G2 Point
+         * @return Error code
+         */
         add_G2(W1, W2, W) {
-                       var P = ctx.ECP8.fromBytes(W1),
-                           Q = ctx.ECP8.fromBytes(W2);
+            var P = ctx.ECP8.fromBytes(W1),
+                Q = ctx.ECP8.fromBytes(W2);
 
-                       if (P.is_infinity() || Q.is_infinity()) {
-                           return this.INVALID_POINT;
-                       }
+            if (P.is_infinity() || Q.is_infinity()) {
+                return this.INVALID_POINT;
+            }
 
-                       P.add(Q);
+            P.add(Q);
 
-                       P.toBytes(W);
+            P.toBytes(W);
 
-                       return 0;
-                }
-	
+            return 0;
+        }
+
     };
 
     return BLS256;
@@ -221,5 +228,3 @@
         BLS256: BLS256
     };
 }
-
-		
diff --git a/test/test_BLS.js b/test/test_BLS.js
index 90df161..1971205 100644
--- a/test/test_BLS.js
+++ b/test/test_BLS.js
@@ -26,7 +26,7 @@
 var expect = chai.expect;
 
 // Curves for test
-var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];
+var pf_curves = ['BLS381','BLS24', 'BLS48'];
 
 pf_curves.forEach(function(curve) {
 
@@ -173,6 +173,34 @@
 	    
             done();
         });
+
+      	it('test externally generated key', function(done) {
+            this.timeout(0);
+
+	    var sk=[];
+	    var pktmp=[];
+	    var pk=[];
+	    var sig=[];
+
+            var RAW = [];
+            rng.clean();
+            for (var j = 0; j < 100; j++) RAW[j] = j;
+            rng.seed(100, RAW);
+
+	    // Key pairs
+	    BLS.KeyPairGenerate(rng,sk,pktmp);
+	    BLS.KeyPairGenerate(null,sk,pk);
+
+	    // Sign message
+	    BLS.sign(sig,message,sk);
+
+	    // Verify signature
+    	    rc=BLS.verify(sig,message,pk);
+
+            expect(rc).to.be.equal(BLS.BLS_OK);
+
+            done();
+        });	
 	
     });
 });