Merge pull request #13 from apache/issue10

Issue10
diff --git a/LICENSE b/LICENSE
index 9b5e401..e873a35 100644
--- a/LICENSE
+++ b/LICENSE
@@ -187,7 +187,7 @@
       same "printed page" as the copyright notice for easier

       identification within third-party archives.

 

-   Copyright [yyyy] [name of copyright owner]

+   Copyright 2018 The Apache Software Foundation

 

    Licensed under the Apache License, Version 2.0 (the "License");

    you may not use this file except in compliance with the License.

diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..77370a4
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Milagro Release
+Copyright 2019 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 381aa3e..43d4f4d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,22 @@
+<!--
+    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.
+-->
+
 # MCJS - *Milagro Crypto JavaScript*
 
 [![Master Branch](https://img.shields.io/badge/-master:-gray.svg)](https://github.com/apache/incubator-milagro-crypto-js/tree/master)
@@ -103,7 +122,10 @@
 
 #### Other functions
 
-MCJS supports SHA256, SHA384, SHA512, AES-GCM encryption and Marsaglia & Zaman random number generator. Those functions are contained in every context initialized with RSA or with an elliptic curve. If you want to create a context supporting only those general functions then initialize it with no parameter as follows:
+MCJS supports SHA256, SHA384, SHA512, AES-GCM encryption and Marsaglia & Zaman
+random number generator. Those functions are contained in every context initialized
+with RSA or with an elliptic curve. If you want to create a context supporting only
+those general functions then initialize it with no parameter as follows:
 
 ```
 var CTX = require("milagro-crypto-js");
@@ -122,7 +144,7 @@
 
 ## Browsers
 
-The library source code is browser compatible. The browser examples are locates
+The library source code is browser compatible. The browser examples are located
 in `./examples/browser`.
 
 ## Docker
@@ -133,6 +155,23 @@
 docker build -t mcjs:builder .
 docker run --rm mcjs:builder 
 ```
+## Crypto Notice
+
+This distribution includes cryptographic software. The country in which you
+currently reside may have restrictions on the import, possession, use, and/or
+re-export to another country, of encryption software. BEFORE using any
+encryption software, please check your country's laws, regulations and
+policies concerning the import, possession, or use, and re-export of encryption
+software, to see if this is permitted. See <http://www.wassenaar.org/> for
+more information.
+
+The Apache Software Foundation has classified this software as Export Commodity
+Control Number (ECCN) 5D002, which includes information security software using
+or performing cryptographic functions with asymmetric algorithms. The form and
+manner of this Apache Software Foundation distribution makes it eligible for
+export under the "publicly available" Section 742.15(b) exemption (see the BIS
+Export Administration Regulations, Section 742.15(b)) for both object code and
+source code.
 
 ## Contributors 
 
@@ -147,11 +186,11 @@
 
 ## Making a Contribution
 
-1.  [Check for open issues](https://github.com/apache/incubator-milagro-crypto-js/issues) or start a discussion around a feature idea or a bug by sending a
-mail to dev@milagro.incubator.apache.org
-2.  Fork the repository to start making your changes. Please use the
-"development" branch as a basis.
-3.  Write a test which shows that the bug was fixed or that the feature works
-as expected.
+1.  [Check for open issues](https://github.com/apache/incubator-milagro-crypto-js/issues)
+    or start a discussion around a feature idea or a bug by sending a mail to
+    dev@milagro.incubator.apache.org
+2.  Fork the repository to start making your changes. Please use the "development" branch
+    as a basis.
+3.  Write a test which shows that the bug was fixed or that the feature works as expected.
 4.  Make a pull request with a reference to the issue
 
diff --git a/doc/AMCL.pdf b/doc/AMCL.pdf
deleted file mode 100644
index e4fa685..0000000
--- a/doc/AMCL.pdf
+++ /dev/null
Binary files differ
diff --git a/docs/aes.md b/docs/aes.md
new file mode 100644
index 0000000..00df09a
--- /dev/null
+++ b/docs/aes.md
@@ -0,0 +1,113 @@
+<a name="AES"></a>
+
+## AES
+**Kind**: global class  
+**this**: <code>{AES}</code>  
+
+* [AES](#AES)
+    * [new AES()](#new_AES_new)
+    * [.reset(m, iv)](#AES+reset)
+    * [.getreg()](#AES+getreg) ⇒
+    * [.init(m, n, key, iv)](#AES+init)
+    * [.ecb_encrypt(buff)](#AES+ecb_encrypt)
+    * [.ecb_decrypt(buff)](#AES+ecb_decrypt)
+    * [.encrypt(buff)](#AES+encrypt)
+    * [.decrypt(buff)](#AES+decrypt)
+    * [.end()](#AES+end)
+
+<a name="new_AES_new"></a>
+
+### new AES()
+Creates an instance of AES.
+
+<a name="AES+reset"></a>
+
+### aeS.reset(m, iv)
+Reset AES mode or IV
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Description |
+| --- | --- |
+| m | The new active mode of operation (ECB, CBC, OFB, CFB etc) |
+| iv | The new Initialisation Vector |
+
+<a name="AES+getreg"></a>
+
+### aeS.getreg() ⇒
+Reset Extract chaining vector
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**Returns**: f the extracted chaining vector  
+**this**: <code>{AES}</code>  
+<a name="AES+init"></a>
+
+### aeS.init(m, n, key, iv)
+Initialise an instance of AES and its mode of operation
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Description |
+| --- | --- |
+| m | is the active mode of operation (ECB, CBC, OFB, CFB etc) |
+| n | is the key length in bytes, 16, 24 or 32 |
+| key | the AES key as an array of 16 bytes |
+| iv | the Initialisation Vector |
+
+<a name="AES+ecb_encrypt"></a>
+
+### aeS.ecb\_encrypt(buff)
+Encrypt a single 16 byte block in ECB mode
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| buff | <code>string</code> | is an array of 16 plaintext bytes, on exit becomes ciphertext |
+
+<a name="AES+ecb_decrypt"></a>
+
+### aeS.ecb\_decrypt(buff)
+Decrypt a single 16 byte block in ECB mode
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Description |
+| --- | --- |
+| buff | is an array of 16 cipherext bytes, on exit becomes plaintext |
+
+<a name="AES+encrypt"></a>
+
+### aeS.encrypt(buff)
+Encrypt using selected mode of operation
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| buff | <code>string</code> | is an array of 16 plaintext bytes, on exit becomes ciphertext |
+
+<a name="AES+decrypt"></a>
+
+### aeS.decrypt(buff)
+Decrypt using selected mode of operation
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| buff | <code>string</code> | is an array of 16 cipherext bytes, on exit becomes plaintext |
+
+<a name="AES+end"></a>
+
+### aeS.end()
+Clean up and delete left-overs
+
+**Kind**: instance method of [<code>AES</code>](#AES)  
+**this**: <code>{AES}</code>  
diff --git a/docs/big.md b/docs/big.md
new file mode 100644
index 0000000..103823d
--- /dev/null
+++ b/docs/big.md
@@ -0,0 +1,528 @@
+<a name="BIG"></a>
+
+## BIG
+**Kind**: global class  
+**this**: <code>{BIG}</code>  
+
+* [BIG](#BIG)
+    * [new BIG()](#new_BIG_new)
+    * _instance_
+        * [.zero()](#BIG+zero) ⇒
+        * [.one()](#BIG+one) ⇒
+        * [.iszilch()](#BIG+iszilch) ⇒
+        * [.isunity()](#BIG+isunity) ⇒
+        * [.cswap()](#BIG+cswap)
+        * [.cmove()](#BIG+cmove)
+        * [.copy()](#BIG+copy) ⇒
+        * [.hcopy()](#BIG+hcopy) ⇒
+        * [.rcopy()](#BIG+rcopy) ⇒
+        * [.norm()](#BIG+norm) ⇒
+        * [.fshr()](#BIG+fshr) ⇒
+        * [.shr()](#BIG+shr) ⇒
+        * [.fshl()](#BIG+fshl) ⇒
+        * [.shl()](#BIG+shl) ⇒
+        * [.nbits()](#BIG+nbits) ⇒
+        * [.toString()](#BIG+toString) ⇒
+        * [.add()](#BIG+add) ⇒
+        * [.or()](#BIG+or) ⇒
+        * [.plus()](#BIG+plus) ⇒
+        * [.inc()](#BIG+inc) ⇒
+        * [.sub()](#BIG+sub) ⇒
+        * [.rsub()](#BIG+rsub) ⇒
+        * [.dec()](#BIG+dec) ⇒
+        * [.minus()](#BIG+minus) ⇒
+        * [.imul()](#BIG+imul) ⇒
+        * [.tobytearray()](#BIG+tobytearray)
+        * [.toBytes()](#BIG+toBytes)
+        * [.muladd()](#BIG+muladd)
+        * [.pmul()](#BIG+pmul) ⇒
+        * [.pxmul()](#BIG+pxmul) ⇒
+        * [.div3()](#BIG+div3) ⇒
+        * [.mod2m()](#BIG+mod2m) ⇒
+        * [.invmod2m()](#BIG+invmod2m) ⇒
+        * [.mod()](#BIG+mod) ⇒
+        * [.div()](#BIG+div) ⇒
+        * [.parity()](#BIG+parity) ⇒
+        * [.bit()](#BIG+bit) ⇒
+        * [.lastbits()](#BIG+lastbits) ⇒
+        * [.jacobi()](#BIG+jacobi) ⇒
+        * [.invmodp()](#BIG+invmodp) ⇒
+        * [.powmod()](#BIG+powmod) ⇒
+    * _static_
+        * [.frombytearray()](#BIG.frombytearray) ⇒
+        * [.smul()](#BIG.smul) ⇒
+        * [.comp()](#BIG.comp) ⇒
+        * [.random()](#BIG.random) ⇒
+        * [.randomnum()](#BIG.randomnum) ⇒
+        * [.mul()](#BIG.mul) ⇒
+        * [.sqr()](#BIG.sqr) ⇒
+        * [.modmul()](#BIG.modmul) ⇒
+        * [.modsqr()](#BIG.modsqr) ⇒
+        * [.modneg()](#BIG.modneg) ⇒
+        * [.invmod256()](#BIG.invmod256) ⇒
+
+<a name="new_BIG_new"></a>
+
+### new BIG()
+General purpose Constructor
+
+<a name="BIG+zero"></a>
+
+### biG.zero() ⇒
+set to zero
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+<a name="BIG+one"></a>
+
+### biG.one() ⇒
+set to one
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+<a name="BIG+iszilch"></a>
+
+### biG.iszilch() ⇒
+test for zero
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: True if zero  
+**this**: <code>{BIG}</code>  
+<a name="BIG+isunity"></a>
+
+### biG.isunity() ⇒
+test for unity
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: True if one  
+**this**: <code>{BIG}</code>  
+<a name="BIG+cswap"></a>
+
+### biG.cswap()
+Conditional swap of two BIGs depending on d using XOR - no branches
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**this**: <code>{BIG}</code>  
+**Parameter**: b BIG number  
+**Parameter**: d BIG number  
+<a name="BIG+cmove"></a>
+
+### biG.cmove()
+Conditional move of BIG depending on d using XOR - no branches
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**this**: <code>{BIG}</code>  
+**Parameter**: b BIG number  
+**Parameter**: d BIG number  
+<a name="BIG+copy"></a>
+
+### biG.copy() ⇒
+Copy from another BIG
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: The BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG number  
+<a name="BIG+hcopy"></a>
+
+### biG.hcopy() ⇒
+copy from bottom half of ctx.DBIG
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: The new BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG number  
+<a name="BIG+rcopy"></a>
+
+### biG.rcopy() ⇒
+copy from ROM
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: The BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG number in ROM  
+<a name="BIG+norm"></a>
+
+### biG.norm() ⇒
+normalise BIG - force all digits < 2^BASEBITS
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+<a name="BIG+fshr"></a>
+
+### biG.fshr() ⇒
+Quick Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: r The shifted out part  
+**this**: <code>{BIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="BIG+shr"></a>
+
+### biG.shr() ⇒
+General shift right by k bits
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="BIG+fshl"></a>
+
+### biG.fshl() ⇒
+Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: r The shifted out part  
+**this**: <code>{BIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="BIG+shl"></a>
+
+### biG.shl() ⇒
+General shift left by k bits
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="BIG+nbits"></a>
+
+### biG.nbits() ⇒
+length in bits
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: The number of bigs in BIG object  
+**this**: <code>{BIG}</code>  
+<a name="BIG+toString"></a>
+
+### biG.toString() ⇒
+Convert to string
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: string representation of a BIG number  
+**this**: <code>{BIG}</code>  
+<a name="BIG+add"></a>
+
+### biG.add() ⇒
+Sum two BIG mumbers
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this+=y  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG object  
+<a name="BIG+or"></a>
+
+### biG.or() ⇒
+OR two BIG mumbers
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this|=y  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG object  
+<a name="BIG+plus"></a>
+
+### biG.plus() ⇒
+Sum two BIG mumbers
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this+x  
+**this**: <code>{BIG}</code>  
+**Parameter**: x BIG object  
+<a name="BIG+inc"></a>
+
+### biG.inc() ⇒
+Sum BIG and integer
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this+=i  
+**this**: <code>{BIG}</code>  
+**Parameter**: i Integer to add  
+<a name="BIG+sub"></a>
+
+### biG.sub() ⇒
+Subtract BIG from one another
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this-=y  
+**this**: <code>{BIG}</code>  
+**Parameter**: y BIG object  
+<a name="BIG+rsub"></a>
+
+### biG.rsub() ⇒
+Reverse subtract BIG from one another
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this=x-this  
+**this**: <code>{BIG}</code>  
+**Parameter**: x BIG object  
+<a name="BIG+dec"></a>
+
+### biG.dec() ⇒
+Subtract integer from BIG
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this-=i  
+**this**: <code>{BIG}</code>  
+**Parameter**: i Integer to subtract  
+<a name="BIG+minus"></a>
+
+### biG.minus() ⇒
+Subtract BIG
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: New BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: x BIG object  
+<a name="BIG+imul"></a>
+
+### biG.imul() ⇒
+Multiply by small integer
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this*c  
+**this**: <code>{BIG}</code>  
+**Parameter**: c small integer  
+<a name="BIG+tobytearray"></a>
+
+### biG.tobytearray()
+convert this BIG to byte array
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**this**: <code>{BIG}</code>  
+<a name="BIG+toBytes"></a>
+
+### biG.toBytes()
+convert this to byte array
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**this**: <code>{BIG}</code>  
+<a name="BIG+muladd"></a>
+
+### biG.muladd()
+this[i]+=x*y+c, and return high part
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**this**: <code>{BIG}</code>  
+<a name="BIG+pmul"></a>
+
+### biG.pmul() ⇒
+multiply by larger int
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: carry value  
+**this**: <code>{BIG}</code>  
+**Parameter**: c large integer  
+<a name="BIG+pxmul"></a>
+
+### biG.pxmul() ⇒
+multiply by still larger int - results requires a DBIG
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: DBIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: c large integer  
+<a name="BIG+div3"></a>
+
+### biG.div3() ⇒
+divide by 3
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: carry value  
+**this**: <code>{BIG}</code>  
+<a name="BIG+mod2m"></a>
+
+### biG.mod2m() ⇒
+set x = x mod 2^m
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: m Exponent  
+<a name="BIG+invmod2m"></a>
+
+### biG.invmod2m() ⇒
+a=1/a mod 2^256. This is very fast!
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+<a name="BIG+mod"></a>
+
+### biG.mod() ⇒
+reduce this mod m
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+<a name="BIG+div"></a>
+
+### biG.div() ⇒
+this/=m1
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Paramter**: m1 divisor  
+<a name="BIG+parity"></a>
+
+### biG.parity() ⇒
+return parity of this
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+<a name="BIG+bit"></a>
+
+### biG.bit() ⇒
+return n-th bit of this
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: bit value  
+**this**: <code>{BIG}</code>  
+**Parameter**: nth bit to return  
+<a name="BIG+lastbits"></a>
+
+### biG.lastbits() ⇒
+return last n bits of this
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: bit values  
+**this**: <code>{BIG}</code>  
+**Parameter**: n bits to return  
+<a name="BIG+jacobi"></a>
+
+### biG.jacobi() ⇒
+Jacobi Symbol (this/p)
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: 0, 1 or -1  
+**this**: <code>{BIG}</code>  
+**Parameter**: p BIG number  
+<a name="BIG+invmodp"></a>
+
+### biG.invmodp() ⇒
+this=1/this mod p. Binary method
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: p The BIG Modulus  
+<a name="BIG+powmod"></a>
+
+### biG.powmod() ⇒
+Exponentation modulo m
+
+**Kind**: instance method of [<code>BIG</code>](#BIG)  
+**Returns**: this^e mod m  
+**this**: <code>{BIG}</code>  
+**Parameter**: e1 BIG number  
+**Parameter**: m  The BIG Modulus  
+<a name="BIG.frombytearray"></a>
+
+### BIG.frombytearray() ⇒
+convert from byte array to BIG
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG object  
+**this**: <code>{BIG}</code>  
+**Parameter**: b Bytearray  
+<a name="BIG.smul"></a>
+
+### BIG.smul() ⇒
+return a*b where product fits a BIG
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: a*b  
+**this**: <code>{BIG}</code>  
+**Parameter**: a BIG number  
+**Parameter**: b BIG number  
+<a name="BIG.comp"></a>
+
+### BIG.comp() ⇒
+Compare a and b
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: 0 if a==b, -1 if a<b, +1 if a>b  
+**this**: <code>{BIG}</code>  
+**Parameter**: a BIG number (normalised)  
+**Parameter**: b BIG number (normalised  
+<a name="BIG.random"></a>
+
+### BIG.random() ⇒
+Get 8*MODBYTES size random number
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+<a name="BIG.randomnum"></a>
+
+### BIG.randomnum() ⇒
+Create random BIG in portable way, one bit at a time
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+**Parameter**: q The BIG Modulus  
+<a name="BIG.mul"></a>
+
+### BIG.mul() ⇒
+Multiple two BIG numbers
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: a*b as a DBIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: a BIG number  
+**Parameter**: b BIG number  
+<a name="BIG.sqr"></a>
+
+### BIG.sqr() ⇒
+Square two BIG numbers
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: a*2 as a DBIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: a BIG number  
+<a name="BIG.modmul"></a>
+
+### BIG.modmul() ⇒
+Multiple two BIG numbers modulo m
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: a1*b1 mod m  as a BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: a1 BIG number  
+**Parameter**: b1 BIG number  
+**Parameter**: m The BIG Modulus  
+<a name="BIG.modsqr"></a>
+
+### BIG.modsqr() ⇒
+Square a BIG number modulo m
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: a*2 mod m  as a BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: a1 BIG number  
+**Parameter**: m The BIG Modulus  
+<a name="BIG.modneg"></a>
+
+### BIG.modneg() ⇒
+Inversion
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: -a1 mod m  
+**this**: <code>{BIG}</code>  
+**Parameter**: a1 BIG number  
+**Parameter**: m The BIG Modulus  
+<a name="BIG.invmod256"></a>
+
+### BIG.invmod256() ⇒
+Arazi and Qi inversion mod 256
+
+**Kind**: static method of [<code>BIG</code>](#BIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: a BIG number  
diff --git a/docs/bls.md b/docs/bls.md
new file mode 100644
index 0000000..910020b
--- /dev/null
+++ b/docs/bls.md
@@ -0,0 +1,104 @@
+<a name="BLS"></a>
+
+## BLS
+**Kind**: global class  
+**this**: <code>{BLS}</code>  
+
+* [BLS](#BLS)
+    * [new BLS()](#new_BLS_new)
+    * [.bytestostring()](#BLS.bytestostring) ⇒
+    * [.stringtobytes()](#BLS.stringtobytes) ⇒
+    * [.bls_hashit()](#BLS.bls_hashit) ⇒
+    * [.KeyPairGenerate()](#BLS.KeyPairGenerate) ⇒
+    * [.sign()](#BLS.sign) ⇒
+    * [.verify()](#BLS.verify) ⇒
+    * [.add_G1()](#BLS.add_G1) ⇒
+    * [.add_G2()](#BLS.add_G2) ⇒
+
+<a name="new_BLS_new"></a>
+
+### new BLS()
+Creates an instance of BLS
+
+<a name="BLS.bytestostring"></a>
+
+### BLS.bytestostring() ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: string  
+**this**: <code>{BLS}</code>  
+**Parameter**: b byte array  
+<a name="BLS.stringtobytes"></a>
+
+### BLS.stringtobytes() ⇒
+Convert string to byte array
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: byte array  
+**this**: <code>{BLS}</code>  
+**Parameter**: s string  
+<a name="BLS.bls_hashit"></a>
+
+### BLS.bls\_hashit() ⇒
+hash a message to an ECP point, using SHA3
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: ECP point  
+**this**: <code>{BLS}</code>  
+**Parameter**: m message to be hashedstring  
+<a name="BLS.KeyPairGenerate"></a>
+
+### BLS.KeyPairGenerate() ⇒
+Generate key pair
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: Error code  
+**this**: <code>{BLS}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+**Parameter**: S Private key  
+**Parameter**: W Public key  
+<a name="BLS.sign"></a>
+
+### BLS.sign() ⇒
+Sign message
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: Error code  
+**this**: <code>{BLS}</code>  
+**Parameter**: SIG Singature  
+**Parameter**: m Message to sign  
+**Parameter**: S Private key  
+<a name="BLS.verify"></a>
+
+### BLS.verify() ⇒
+Verify message
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: Error code  
+**this**: <code>{BLS}</code>  
+**Parameter**: SIG Signature  
+**Parameter**: m Message to sign  
+**Parameter**: W Public key  
+<a name="BLS.add_G1"></a>
+
+### BLS.add\_G1() ⇒
+R=R1+R2 in group G1
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: Error code  
+**this**: <code>{BLS}</code>  
+**Parameter**: R1 G1 Point  
+**Parameter**: R2 G1 Point  
+**Parameter**: R G1 Point  
+<a name="BLS.add_G2"></a>
+
+### BLS.add\_G2() ⇒
+W=W1+W2 in group G2
+
+**Kind**: static method of [<code>BLS</code>](#BLS)  
+**Returns**: Error code  
+**this**: <code>{BLS}</code>  
+**Parameter**: W1 G2 Point  
+**Parameter**: W2 G2 Point  
+**Parameter**: R G2 Point  
diff --git a/docs/bls192.md b/docs/bls192.md
new file mode 100644
index 0000000..2ff5d83
--- /dev/null
+++ b/docs/bls192.md
@@ -0,0 +1,104 @@
+<a name="BLS192"></a>
+
+## BLS192
+**Kind**: global class  
+**this**: <code>{BLS192}</code>  
+
+* [BLS192](#BLS192)
+    * [new BLS192()](#new_BLS192_new)
+    * [.bytestostring()](#BLS192.bytestostring) ⇒
+    * [.stringtobytes()](#BLS192.stringtobytes) ⇒
+    * [.bls_hashit()](#BLS192.bls_hashit) ⇒
+    * [.KeyPairGenerate()](#BLS192.KeyPairGenerate) ⇒
+    * [.sign()](#BLS192.sign) ⇒
+    * [.verify()](#BLS192.verify) ⇒
+    * [.add_G1()](#BLS192.add_G1) ⇒
+    * [.add_G2()](#BLS192.add_G2) ⇒
+
+<a name="new_BLS192_new"></a>
+
+### new BLS192()
+Creates an instance of BLS192
+
+<a name="BLS192.bytestostring"></a>
+
+### BLS192.bytestostring() ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: string  
+**this**: <code>{BLS192}</code>  
+**Parameter**: b byte array  
+<a name="BLS192.stringtobytes"></a>
+
+### BLS192.stringtobytes() ⇒
+Convert string to byte array
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: byte array  
+**this**: <code>{BLS192}</code>  
+**Parameter**: s string  
+<a name="BLS192.bls_hashit"></a>
+
+### BLS192.bls\_hashit() ⇒
+hash a message to an ECP point, using SHA3
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: ECP point  
+**this**: <code>{BLS192}</code>  
+**Parameter**: m message to be hashedstring  
+<a name="BLS192.KeyPairGenerate"></a>
+
+### BLS192.KeyPairGenerate() ⇒
+Generate key pair
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+**Parameter**: S Private key  
+**Parameter**: W Public key  
+<a name="BLS192.sign"></a>
+
+### BLS192.sign() ⇒
+Sign message
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: SIG Singature  
+**Parameter**: m Message to sign  
+**Parameter**: S Private key  
+<a name="BLS192.verify"></a>
+
+### BLS192.verify() ⇒
+Verify message
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: SIG Signature  
+**Parameter**: m Message to sign  
+**Parameter**: W Public key  
+<a name="BLS192.add_G1"></a>
+
+### BLS192.add\_G1() ⇒
+R=R1+R2 in group G1
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: R1 G1 Point  
+**Parameter**: R2 G1 Point  
+**Parameter**: R G1 Point  
+<a name="BLS192.add_G2"></a>
+
+### BLS192.add\_G2() ⇒
+W=W1+W2 in group G2
+
+**Kind**: static method of [<code>BLS192</code>](#BLS192)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: W1 G2 Point  
+**Parameter**: W2 G2 Point  
+**Parameter**: R G2 Point  
diff --git a/docs/bls256.md b/docs/bls256.md
new file mode 100644
index 0000000..528dd3f
--- /dev/null
+++ b/docs/bls256.md
@@ -0,0 +1,104 @@
+<a name="BLS256"></a>
+
+## BLS256
+**Kind**: global class  
+**this**: <code>{BLS256}</code>  
+
+* [BLS256](#BLS256)
+    * [new BLS256()](#new_BLS256_new)
+    * [.bytestostring()](#BLS256.bytestostring) ⇒
+    * [.stringtobytes()](#BLS256.stringtobytes) ⇒
+    * [.bls_hashit()](#BLS256.bls_hashit) ⇒
+    * [.KeyPairGenerate()](#BLS256.KeyPairGenerate) ⇒
+    * [.sign()](#BLS256.sign) ⇒
+    * [.verify()](#BLS256.verify) ⇒
+    * [.add_G1()](#BLS256.add_G1) ⇒
+    * [.add_G2()](#BLS256.add_G2) ⇒
+
+<a name="new_BLS256_new"></a>
+
+### new BLS256()
+Creates an instance of BLS256
+
+<a name="BLS256.bytestostring"></a>
+
+### BLS256.bytestostring() ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: string  
+**this**: <code>{BLS192}</code>  
+**Parameter**: b byte array  
+<a name="BLS256.stringtobytes"></a>
+
+### BLS256.stringtobytes() ⇒
+Convert string to byte array
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: byte array  
+**this**: <code>{BLS192}</code>  
+**Parameter**: s string  
+<a name="BLS256.bls_hashit"></a>
+
+### BLS256.bls\_hashit() ⇒
+hash a message to an ECP point, using SHA3
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: ECP point  
+**this**: <code>{BLS192}</code>  
+**Parameter**: m message to be hashedstring  
+<a name="BLS256.KeyPairGenerate"></a>
+
+### BLS256.KeyPairGenerate() ⇒
+Generate key pair
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+**Parameter**: S Private key  
+**Parameter**: W Public key  
+<a name="BLS256.sign"></a>
+
+### BLS256.sign() ⇒
+Sign message
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: SIG Singature  
+**Parameter**: m Message to sign  
+**Parameter**: S Private key  
+<a name="BLS256.verify"></a>
+
+### BLS256.verify() ⇒
+Verify message
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: SIG Signature  
+**Parameter**: m Message to sign  
+**Parameter**: W Public key  
+<a name="BLS256.add_G1"></a>
+
+### BLS256.add\_G1() ⇒
+R=R1+R2 in group G1
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: R1 G1 Point  
+**Parameter**: R2 G1 Point  
+**Parameter**: R G1 Point  
+<a name="BLS256.add_G2"></a>
+
+### BLS256.add\_G2() ⇒
+W=W1+W2 in group G2
+
+**Kind**: static method of [<code>BLS256</code>](#BLS256)  
+**Returns**: Error code  
+**this**: <code>{BLS192}</code>  
+**Parameter**: W1 G2 Point  
+**Parameter**: W2 G2 Point  
+**Parameter**: R G2 Point  
diff --git a/docs/dbig.md b/docs/dbig.md
new file mode 100644
index 0000000..ef95efe
--- /dev/null
+++ b/docs/dbig.md
@@ -0,0 +1,170 @@
+<a name="DBIG"></a>
+
+## DBIG
+**Kind**: global class  
+**this**: <code>{DBIG}</code>  
+
+* [DBIG](#DBIG)
+    * [new DBIG()](#new_DBIG_new)
+    * _instance_
+        * [.zero()](#DBIG+zero) ⇒
+        * [.copy()](#DBIG+copy) ⇒
+        * [.hcopy()](#DBIG+hcopy) ⇒
+        * [.norm()](#DBIG+norm) ⇒
+        * [.muladd()](#DBIG+muladd)
+        * [.shr()](#DBIG+shr) ⇒
+        * [.shl()](#DBIG+shl) ⇒
+        * [.cmove()](#DBIG+cmove)
+        * [.add()](#DBIG+add) ⇒
+        * [.sub()](#DBIG+sub) ⇒
+        * [.nbits()](#DBIG+nbits) ⇒
+        * [.toString()](#DBIG+toString) ⇒
+        * [.mod()](#DBIG+mod) ⇒
+        * [.div()](#DBIG+div) ⇒
+        * [.split()](#DBIG+split) ⇒
+    * _static_
+        * [.comp()](#DBIG.comp) ⇒
+
+<a name="new_DBIG_new"></a>
+
+### new DBIG()
+General purpose Constructor
+
+<a name="DBIG+zero"></a>
+
+### dbiG.zero() ⇒
+set to zero
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: BIG number  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+copy"></a>
+
+### dbiG.copy() ⇒
+set to b
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: DBIG number  
+**this**: <code>{DBIG}</code>  
+**Parameter**: b DBIG number  
+<a name="DBIG+hcopy"></a>
+
+### dbiG.hcopy() ⇒
+copy from ctx.BIG
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: DBIG number  
+**this**: <code>{DBIG}</code>  
+**Parameter**: b BIG number  
+<a name="DBIG+norm"></a>
+
+### dbiG.norm() ⇒
+normalise DBIG - force all digits < 2^BASEBITS
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: DBIG number  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+muladd"></a>
+
+### dbiG.muladd()
+this[i]+=x*y+c, and return high part
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+shr"></a>
+
+### dbiG.shr() ⇒
+General shift right by k bits
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: BIG number  
+**this**: <code>{DBIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="DBIG+shl"></a>
+
+### dbiG.shl() ⇒
+General shift left by k bits
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: BIG number  
+**this**: <code>{BIG}</code>  
+**Parameter**: k Number of bits to shift  
+<a name="DBIG+cmove"></a>
+
+### dbiG.cmove()
+Conditional move of BIG depending on d using XOR - no branches
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**this**: <code>{DBIG}</code>  
+**Parameter**: b DBIG number  
+**Parameter**: d DBIG number  
+<a name="DBIG+add"></a>
+
+### dbiG.add() ⇒
+Sum two DBIG mumbers
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: this+=x  
+**this**: <code>{DBIG}</code>  
+**Parameter**: x DBIG object  
+<a name="DBIG+sub"></a>
+
+### dbiG.sub() ⇒
+Subtract DBIG from one another
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: this-=x  
+**this**: <code>{DBIG}</code>  
+**Parameter**: x BIG object  
+<a name="DBIG+nbits"></a>
+
+### dbiG.nbits() ⇒
+length in bits
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: The number of bigs in DBIG object  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+toString"></a>
+
+### dbiG.toString() ⇒
+Convert to string
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: string representation of a BIG number  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+mod"></a>
+
+### dbiG.mod() ⇒
+reduces this DBIG mod a ctx.BIG, and returns the ctx.BIG
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: BIG object  
+**this**: <code>{DBIG}</code>  
+<a name="DBIG+div"></a>
+
+### dbiG.div() ⇒
+this/=c
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: DBIG number  
+**this**: <code>{DBIG}</code>  
+**Paramter**: c divisor  
+<a name="DBIG+split"></a>
+
+### dbiG.split() ⇒
+split this DBIG at position n, return higher half, keep lower half
+
+**Kind**: instance method of [<code>DBIG</code>](#DBIG)  
+**Returns**: lower half BIG number  
+**this**: <code>{DBIG}</code>  
+**Paramter**: n Position to splitdivisor  
+<a name="DBIG.comp"></a>
+
+### DBIG.comp() ⇒
+Compare a and b
+
+**Kind**: static method of [<code>DBIG</code>](#DBIG)  
+**Returns**: 0 if a==b, -1 if a<b, +1 if a>b  
+**this**: <code>{DBIG}</code>  
+**Parameter**: a DBIG number (normalised)  
+**Parameter**: b DBIG number (normalised  
diff --git a/docs/ecdh.md b/docs/ecdh.md
new file mode 100644
index 0000000..68fec62
--- /dev/null
+++ b/docs/ecdh.md
@@ -0,0 +1,216 @@
+<a name="ECDH"></a>
+
+## ECDH
+**Kind**: global class  
+**this**: <code>{ECDH}</code>  
+
+* [ECDH](#ECDH)
+    * [new ECDH()](#new_ECDH_new)
+    * [.inttobytes()](#ECDH.inttobytes) ⇒
+    * [.bytestostring()](#ECDH.bytestostring) ⇒
+    * [.stringtobytes()](#ECDH.stringtobytes) ⇒
+    * [.hashit()](#ECDH.hashit) ⇒
+    * [.KDF2()](#ECDH.KDF2) ⇒
+    * [.PBKDF2()](#ECDH.PBKDF2) ⇒
+    * [.HMAC()](#ECDH.HMAC) ⇒
+    * [.AES_CBC_IV0_ENCRYPT()](#ECDH.AES_CBC_IV0_ENCRYPT) ⇒
+    * [.AES_CBC_IV0_DECRYPT()](#ECDH.AES_CBC_IV0_DECRYPT) ⇒
+    * [.KEY_PAIR_GENERATE()](#ECDH.KEY_PAIR_GENERATE) ⇒
+    * [.PUBLIC_KEY_VALIDATE()](#ECDH.PUBLIC_KEY_VALIDATE) ⇒
+    * [.ECPSVDP_DH()](#ECDH.ECPSVDP_DH) ⇒
+    * [.ECPSP_DSA()](#ECDH.ECPSP_DSA) ⇒
+    * [.ECPVP_DSA()](#ECDH.ECPVP_DSA) ⇒
+    * [.ECIES_ENCRYPT()](#ECDH.ECIES_ENCRYPT) ⇒
+    * [.ECIES_DECRYPT()](#ECDH.ECIES_DECRYPT) ⇒
+
+<a name="new_ECDH_new"></a>
+
+### new ECDH()
+Creates an instance of ECDH
+
+<a name="ECDH.inttobytes"></a>
+
+### ECDH.inttobytes() ⇒
+Convert Integer to n-byte array
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: byte array  
+**this**: <code>{ECDH}</code>  
+**Parameter**: n integer  
+**Parameter**: len integer length  
+<a name="ECDH.bytestostring"></a>
+
+### ECDH.bytestostring() ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: string  
+**this**: <code>{ECDH}</code>  
+**Parameter**: b byte array  
+<a name="ECDH.stringtobytes"></a>
+
+### ECDH.stringtobytes() ⇒
+Convert string to byte array
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: byte array  
+**this**: <code>{ECDH}</code>  
+**Parameter**: s string  
+<a name="ECDH.hashit"></a>
+
+### ECDH.hashit() ⇒
+general purpose hash function w=hash(B|n)
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: w output  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: A byte array involved in the hash  
+**Parameter**: n integer involved in the hash  
+**Parameter**: pad padding  
+<a name="ECDH.KDF2"></a>
+
+### ECDH.KDF2() ⇒
+IEEE-1363 Key Derivation Function - generates key K from inputs Z and P
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: K derived key  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: Z input byte array  
+**Parameter**: P input key derivation parameters - can be NULL  
+**Parameter**: 0len is output desired length of key  
+<a name="ECDH.PBKDF2"></a>
+
+### ECDH.PBKDF2() ⇒
+Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: key derived key  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: Pass input password  
+**Parameter**: Salt salt value  
+**Parameter**: rep Number of times to be iterated.  
+**Parameter**: 0len is output desired length of key  
+<a name="ECDH.HMAC"></a>
+
+### ECDH.HMAC() ⇒
+HMAC of message M using key K to create tag of length tag.length
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: M input message  
+**Parameter**: K input encryption key  
+**Parameter**: tag is the output HMAC  
+<a name="ECDH.AES_CBC_IV0_ENCRYPT"></a>
+
+### ECDH.AES\_CBC\_IV0\_ENCRYPT() ⇒
+AES encrypts a plaintext to a ciphtertext
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: C Ciphertext  
+**this**: <code>{ECDH}</code>  
+**Parameter**: M input message  
+**Parameter**: K AES key  
+<a name="ECDH.AES_CBC_IV0_DECRYPT"></a>
+
+### ECDH.AES\_CBC\_IV0\_DECRYPT() ⇒
+AES encrypts a plaintext to a ciphtertext
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: P Plaintext  
+**this**: <code>{ECDH}</code>  
+**Parameter**: C Ciphertext  
+**Parameter**: K AES key  
+<a name="ECDH.KEY_PAIR_GENERATE"></a>
+
+### ECDH.KEY\_PAIR\_GENERATE() ⇒
+Generate an ECC public/private key pair
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: 0 or an error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: rng Cryptographically Secure Random Number Generator  
+**Parameter**: S the private key  
+**Parameter**: W the output public key, which is s.G, where G is a fixed generator  
+<a name="ECDH.PUBLIC_KEY_VALIDATE"></a>
+
+### ECDH.PUBLIC\_KEY\_VALIDATE() ⇒
+Generate an ECC public/private key pair
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: 0 or an error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: W the input public key to be validated  
+<a name="ECDH.ECPSVDP_DH"></a>
+
+### ECDH.ECPSVDP\_DH() ⇒
+Generate Diffie-Hellman shared key
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: 0 or an error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: S the private key  
+**Parameter**: W the output public key, which is s.G, where G is a fixed generator  
+**Parameter**: K the output shared key, in fact the x-coordinate of s.W  
+<a name="ECDH.ECPSP_DSA"></a>
+
+### ECDH.ECPSP\_DSA() ⇒
+ECDSA Signature
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: 0 or an error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: RNG Cryptographically Secure Random Number Generator  
+**Parameter**: S the private key  
+**Parameter**: F the input message to be signed  
+**Parameter**: C component of the output signature  
+**Parameter**: D component of the output signature  
+<a name="ECDH.ECPVP_DSA"></a>
+
+### ECDH.ECPVP\_DSA() ⇒
+ECDSA Signature Verification
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: 0 or an error code  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: W the public key  
+**Parameter**: F the input message to be signed  
+**Parameter**: C component of the output signature  
+**Parameter**: D component of the output signature  
+<a name="ECDH.ECIES_ENCRYPT"></a>
+
+### ECDH.ECIES\_ENCRYPT() ⇒
+ECIES Encryption
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: C ciphertext  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: P1 input Key Derivation parameters  
+**Parameter**: P2 input Encoding parameters  
+**Parameter**: RNG Cryptographically Secure Random Number Generator  
+**Parameter**: W the public key  
+**Parameter**: M the input message to be encrypted  
+**Parameter**: V component of the output ciphertext  
+**Parameter**: T the output HMAC tag, part of the ciphertext  
+<a name="ECDH.ECIES_DECRYPT"></a>
+
+### ECDH.ECIES\_DECRYPT() ⇒
+ECIES Encryption
+
+**Kind**: static method of [<code>ECDH</code>](#ECDH)  
+**Returns**: M plaintext  
+**this**: <code>{ECDH}</code>  
+**Parameter**: sha is the hash type  
+**Parameter**: P1 input Key Derivation parameters  
+**Parameter**: P2 input Encoding parameters  
+**Parameter**: V component of the output ciphertext  
+**Parameter**: C Ciphertext  
+**Parameter**: T the output HMAC tag, part of the ciphertext  
+**Parameter**: U the private key  
diff --git a/docs/ecp.md b/docs/ecp.md
new file mode 100644
index 0000000..719d518
--- /dev/null
+++ b/docs/ecp.md
@@ -0,0 +1,316 @@
+<a name="ECP"></a>
+
+## ECP
+**Kind**: global class  
+**this**: <code>{ECP}</code>  
+
+* [ECP](#ECP)
+    * [new ECP()](#new_ECP_new)
+    * _instance_
+        * [.is_infinity(1)](#ECP+is_infinity)
+        * [.cswap()](#ECP+cswap)
+        * [.cmove()](#ECP+cmove)
+        * [.select()](#ECP+select)
+        * [.copy(P)](#ECP+copy)
+        * [.neg()](#ECP+neg)
+        * [.inf()](#ECP+inf)
+        * [.setxy(ix, iy)](#ECP+setxy)
+        * [.setxi(ix, s)](#ECP+setxi)
+        * [.setx(ix)](#ECP+setx)
+        * [.affine()](#ECP+affine)
+        * [.getX()](#ECP+getX)
+        * [.getY()](#ECP+getY)
+        * [.getS()](#ECP+getS)
+        * [.getx()](#ECP+getx)
+        * [.gety()](#ECP+gety)
+        * [.getz()](#ECP+getz)
+        * [.toBytes(b)](#ECP+toBytes)
+        * [.toString()](#ECP+toString) ⇒
+        * [.dbl()](#ECP+dbl)
+        * [.add()](#ECP+add)
+        * [.sub(Q)](#ECP+sub)
+        * [.pinmul(e, bts)](#ECP+pinmul)
+        * [.cfp()](#ECP+cfp)
+        * [.mul(e)](#ECP+mul)
+        * [.mul2(e, Q, f)](#ECP+mul2)
+    * _static_
+        * [.generator()](#ECP.generator)
+        * [.fromBytes(b)](#ECP.fromBytes)
+        * [.RHS(x)](#ECP.RHS)
+
+<a name="new_ECP_new"></a>
+
+### new ECP()
+Creates an instance of ECP
+
+<a name="ECP+is_infinity"></a>
+
+### ecP.is\_infinity(1)
+Tests for ECP point equal to infinity
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| 1 | if infinity, else returns 0 |
+
+<a name="ECP+cswap"></a>
+
+### ecP.cswap()
+conditional swap of this and Q dependant on dCopy ECP point to another ECP point
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+cmove"></a>
+
+### ecP.cmove()
+conditional move of Q to P dependant on d
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+select"></a>
+
+### ecP.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+copy"></a>
+
+### ecP.copy(P)
+Copy ECP point to another ECP point
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | ECP instance |
+
+<a name="ECP+neg"></a>
+
+### ecP.neg()
+set this=-this
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+inf"></a>
+
+### ecP.inf()
+Set ECP to point-at-infinity
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+setxy"></a>
+
+### ecP.setxy(ix, iy)
+set this=(x,y)
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+| iy | y-value |
+
+<a name="ECP+setxi"></a>
+
+### ecP.setxi(ix, s)
+set this=x, where x is ctx.BIG, y is derived from sign s
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+| s | sign to derive y |
+
+<a name="ECP+setx"></a>
+
+### ecP.setx(ix)
+set this=x, y calculated from curve equation
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+
+<a name="ECP+affine"></a>
+
+### ecP.affine()
+convert this to affine, from (x,y,z) to (x,y)
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+getX"></a>
+
+### ecP.getX()
+extract affine x as ctx.FP2
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+getY"></a>
+
+### ecP.getY()
+extract affine y as ctx.FP2
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+getS"></a>
+
+### ecP.getS()
+get sign of Y
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+getx"></a>
+
+### ecP.getx()
+extract x as ctx.FP
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+gety"></a>
+
+### ecP.gety()
+extract y as ctx.FP
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+getz"></a>
+
+### ecP.getz()
+extract z as ctx.FP
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+toBytes"></a>
+
+### ecP.toBytes(b)
+convert this to byte arrayextract projective x
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array output |
+
+<a name="ECP+toString"></a>
+
+### ecP.toString() ⇒
+convert this to hex string
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**Returns**: hex string  
+**this**: <code>{ECP}</code>  
+<a name="ECP+dbl"></a>
+
+### ecP.dbl()
+this+=this
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+add"></a>
+
+### ecP.add()
+Adds ECP instances
+
+param Q ECP instance
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+sub"></a>
+
+### ecP.sub(Q)
+Subtracts ECP instance Q  from this
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP instance |
+
+<a name="ECP+pinmul"></a>
+
+### ecP.pinmul(e, bts)
+constant time multiply by small integer of length bts - use ladder
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | small integer |
+| bts | e bit length |
+
+<a name="ECP+cfp"></a>
+
+### ecP.cfp()
+multiply this by the curves cofactor
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP+mul"></a>
+
+### ecP.mul(e)
+Multiplies an ECP instance P by a BIG, side-channel resistant
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG number multiplier |
+
+<a name="ECP+mul2"></a>
+
+### ecP.mul2(e, Q, f)
+Return e.this+f.Q
+
+**Kind**: instance method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG number multiplier |
+| Q | ECP instance |
+| f | BIG number multiplier |
+
+<a name="ECP.generator"></a>
+
+### ECP.generator()
+Set group generator
+
+**Kind**: static method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+<a name="ECP.fromBytes"></a>
+
+### ECP.fromBytes(b)
+convert from byte array to point
+
+**Kind**: static method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | input byte array |
+
+<a name="ECP.RHS"></a>
+
+### ECP.RHS(x)
+Calculate RHS of the curve equation
+
+**Kind**: static method of [<code>ECP</code>](#ECP)  
+**this**: <code>{ECP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | x-value |
+
diff --git a/docs/ecp2.md b/docs/ecp2.md
new file mode 100644
index 0000000..8bc9567
--- /dev/null
+++ b/docs/ecp2.md
@@ -0,0 +1,278 @@
+<a name="ECP2"></a>
+
+## ECP2
+**Kind**: global class  
+**this**: <code>{ECP2}</code>  
+
+* [ECP2](#ECP2)
+    * [new ECP2()](#new_ECP2_new)
+    * _instance_
+        * [.is_infinity(1)](#ECP2+is_infinity)
+        * [.copy(P)](#ECP2+copy)
+        * [.inf()](#ECP2+inf)
+        * [.cmove()](#ECP2+cmove)
+        * [.select()](#ECP2+select)
+        * [.equals(Q)](#ECP2+equals)
+        * [.neg()](#ECP2+neg)
+        * [.affine()](#ECP2+affine)
+        * [.getX()](#ECP2+getX)
+        * [.getY()](#ECP2+getY)
+        * [.getx()](#ECP2+getx)
+        * [.gety()](#ECP2+gety)
+        * [.getz()](#ECP2+getz)
+        * [.toBytes(b)](#ECP2+toBytes)
+        * [.toString()](#ECP2+toString) ⇒
+        * [.setxy(ix, iy)](#ECP2+setxy)
+        * [.setx(ix)](#ECP2+setx)
+        * [.frob()](#ECP2+frob)
+        * [.dbl()](#ECP2+dbl)
+        * [.add()](#ECP2+add)
+        * [.sub(Q)](#ECP2+sub)
+        * [.mul(e)](#ECP2+mul)
+    * _static_
+        * [.generator()](#ECP2.generator)
+        * [.fromBytes(b)](#ECP2.fromBytes)
+        * [.RHS(x)](#ECP2.RHS)
+        * [.mul4()](#ECP2.mul4)
+
+<a name="new_ECP2_new"></a>
+
+### new ECP2()
+Creates an instance of ECP2
+
+<a name="ECP2+is_infinity"></a>
+
+### ecP2.is\_infinity(1)
+Tests for ECP2 point equal to infinity
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| 1 | if infinity, else returns 0 |
+
+<a name="ECP2+copy"></a>
+
+### ecP2.copy(P)
+Copy ECP2 point to another ECP2 point
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | ECP2 instance |
+
+<a name="ECP2+inf"></a>
+
+### ecP2.inf()
+Set ECP2 to point-at-infinity
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+cmove"></a>
+
+### ecP2.cmove()
+conditional move of Q to P dependant on d
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+select"></a>
+
+### ecP2.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+equals"></a>
+
+### ecP2.equals(Q)
+Test P == Q
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP2 instance |
+
+<a name="ECP2+neg"></a>
+
+### ecP2.neg()
+set this=-this
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+affine"></a>
+
+### ecP2.affine()
+convert this to affine, from (x,y,z) to (x,y)
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+getX"></a>
+
+### ecP2.getX()
+extract affine x as ctx.FP2
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+getY"></a>
+
+### ecP2.getY()
+extract affine y as ctx.FP2
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+getx"></a>
+
+### ecP2.getx()
+extract projective x
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+gety"></a>
+
+### ecP2.gety()
+extract projective y
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+getz"></a>
+
+### ecP2.getz()
+extract projective z
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+toBytes"></a>
+
+### ecP2.toBytes(b)
+convert this to byte arrayextract projective x
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array output |
+
+<a name="ECP2+toString"></a>
+
+### ecP2.toString() ⇒
+convert this to hex string
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**Returns**: hex string  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+setxy"></a>
+
+### ecP2.setxy(ix, iy)
+set this=(x,y)
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+| iy | y-value |
+
+<a name="ECP2+setx"></a>
+
+### ecP2.setx(ix)
+set this=(x,.)
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+
+<a name="ECP2+frob"></a>
+
+### ecP2.frob()
+set this*=q, where q is Modulus, using Frobenius
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+dbl"></a>
+
+### ecP2.dbl()
+this+=this
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+add"></a>
+
+### ecP2.add()
+Adds ECP2 instances
+
+param Q ECP2 instance
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2+sub"></a>
+
+### ecP2.sub(Q)
+Subtracts ECP instance Q  from this
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP2 instance |
+
+<a name="ECP2+mul"></a>
+
+### ecP2.mul(e)
+Multiplies an ECP2 instance P by a BIG, side-channel resistant
+
+**Kind**: instance method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG number multiplier |
+
+<a name="ECP2.generator"></a>
+
+### ECP2.generator()
+Set group generator
+
+**Kind**: static method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+<a name="ECP2.fromBytes"></a>
+
+### ECP2.fromBytes(b)
+convert from byte array to point
+
+**Kind**: static method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | input byte array |
+
+<a name="ECP2.RHS"></a>
+
+### ECP2.RHS(x)
+Calculate RHS of curve equation x^3+B
+
+**Kind**: static method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | x-value |
+
+<a name="ECP2.mul4"></a>
+
+### ECP2.mul4()
+Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3
+
+**Kind**: static method of [<code>ECP2</code>](#ECP2)  
+**this**: <code>{ECP2}</code>  
diff --git a/docs/ecp4.md b/docs/ecp4.md
new file mode 100644
index 0000000..0d23c18
--- /dev/null
+++ b/docs/ecp4.md
@@ -0,0 +1,278 @@
+<a name="ECP4"></a>
+
+## ECP4
+**Kind**: global class  
+**this**: <code>{ECP4}</code>  
+
+* [ECP4](#ECP4)
+    * [new ECP4()](#new_ECP4_new)
+    * _instance_
+        * [.is_infinity(1)](#ECP4+is_infinity)
+        * [.copy(P)](#ECP4+copy)
+        * [.inf()](#ECP4+inf)
+        * [.cmove()](#ECP4+cmove)
+        * [.select()](#ECP4+select)
+        * [.equals(Q)](#ECP4+equals)
+        * [.neg()](#ECP4+neg)
+        * [.affine()](#ECP4+affine)
+        * [.getX()](#ECP4+getX)
+        * [.getY()](#ECP4+getY)
+        * [.getx()](#ECP4+getx)
+        * [.gety()](#ECP4+gety)
+        * [.getz()](#ECP4+getz)
+        * [.toBytes(b)](#ECP4+toBytes)
+        * [.toString()](#ECP4+toString) ⇒
+        * [.setxy(ix, iy)](#ECP4+setxy)
+        * [.setx(ix)](#ECP4+setx)
+        * [.frob()](#ECP4+frob)
+        * [.dbl()](#ECP4+dbl)
+        * [.add()](#ECP4+add)
+        * [.sub(Q)](#ECP4+sub)
+        * [.mul(e)](#ECP4+mul)
+    * _static_
+        * [.generator()](#ECP4.generator)
+        * [.fromBytes(b)](#ECP4.fromBytes)
+        * [.RHS(x)](#ECP4.RHS)
+        * [.mul8()](#ECP4.mul8)
+
+<a name="new_ECP4_new"></a>
+
+### new ECP4()
+Creates an instance of ECP4
+
+<a name="ECP4+is_infinity"></a>
+
+### ecP4.is\_infinity(1)
+Tests for ECP4 point equal to infinity
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| 1 | if infinity, else returns 0 |
+
+<a name="ECP4+copy"></a>
+
+### ecP4.copy(P)
+Copy ECP4 point to another ECP4 point
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | ECP4 instance |
+
+<a name="ECP4+inf"></a>
+
+### ecP4.inf()
+conditional move of Q to P dependant on d
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+cmove"></a>
+
+### ecP4.cmove()
+conditional move of Q to P dependant on d
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+select"></a>
+
+### ecP4.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+equals"></a>
+
+### ecP4.equals(Q)
+Test P == Q
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP4 instance |
+
+<a name="ECP4+neg"></a>
+
+### ecP4.neg()
+set this=-this
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+affine"></a>
+
+### ecP4.affine()
+convert this to affine, from (x,y,z) to (x,y)
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+getX"></a>
+
+### ecP4.getX()
+extract affine x as ctx.FP2
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+getY"></a>
+
+### ecP4.getY()
+extract affine y as ctx.FP2
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+getx"></a>
+
+### ecP4.getx()
+extract projective x
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+gety"></a>
+
+### ecP4.gety()
+extract projective y
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+getz"></a>
+
+### ecP4.getz()
+extract projective z
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+toBytes"></a>
+
+### ecP4.toBytes(b)
+convert this to byte arrayextract projective x
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array output |
+
+<a name="ECP4+toString"></a>
+
+### ecP4.toString() ⇒
+convert this to hex string
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**Returns**: hex string  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+setxy"></a>
+
+### ecP4.setxy(ix, iy)
+set this=(x,y)
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+| iy | y-value |
+
+<a name="ECP4+setx"></a>
+
+### ecP4.setx(ix)
+set this=(x,.)
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+
+<a name="ECP4+frob"></a>
+
+### ecP4.frob()
+set this*=q, where q is Modulus, using Frobenius
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+dbl"></a>
+
+### ecP4.dbl()
+this+=this
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+add"></a>
+
+### ecP4.add()
+Adds ECP4 instances
+
+param Q ECP4 instance
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4+sub"></a>
+
+### ecP4.sub(Q)
+Subtracts ECP instance Q  from this
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP4 instance |
+
+<a name="ECP4+mul"></a>
+
+### ecP4.mul(e)
+Multiplies an ECP4 instance P by a BIG, side-channel resistant
+
+**Kind**: instance method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG number multiplier |
+
+<a name="ECP4.generator"></a>
+
+### ECP4.generator()
+Set group generator
+
+**Kind**: static method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+<a name="ECP4.fromBytes"></a>
+
+### ECP4.fromBytes(b)
+convert from byte array to point
+
+**Kind**: static method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | input byte array |
+
+<a name="ECP4.RHS"></a>
+
+### ECP4.RHS(x)
+Calculate RHS of curve equation x^3+B
+
+**Kind**: static method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | x-value |
+
+<a name="ECP4.mul8"></a>
+
+### ECP4.mul8()
+Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3...
+
+**Kind**: static method of [<code>ECP4</code>](#ECP4)  
+**this**: <code>{ECP4}</code>  
diff --git a/docs/ecp8.md b/docs/ecp8.md
new file mode 100644
index 0000000..7a221c9
--- /dev/null
+++ b/docs/ecp8.md
@@ -0,0 +1,278 @@
+<a name="ECP8"></a>
+
+## ECP8
+**Kind**: global class  
+**this**: <code>{ECP8}</code>  
+
+* [ECP8](#ECP8)
+    * [new ECP8()](#new_ECP8_new)
+    * _instance_
+        * [.is_infinity(1)](#ECP8+is_infinity)
+        * [.copy(P)](#ECP8+copy)
+        * [.inf()](#ECP8+inf)
+        * [.cmove()](#ECP8+cmove)
+        * [.select()](#ECP8+select)
+        * [.equals(Q)](#ECP8+equals)
+        * [.neg()](#ECP8+neg)
+        * [.affine()](#ECP8+affine)
+        * [.getX()](#ECP8+getX)
+        * [.getY()](#ECP8+getY)
+        * [.getx()](#ECP8+getx)
+        * [.gety()](#ECP8+gety)
+        * [.getz()](#ECP8+getz)
+        * [.toBytes(b)](#ECP8+toBytes)
+        * [.toString()](#ECP8+toString) ⇒
+        * [.setxy(ix, iy)](#ECP8+setxy)
+        * [.setx(ix)](#ECP8+setx)
+        * [.frob()](#ECP8+frob)
+        * [.dbl()](#ECP8+dbl)
+        * [.add()](#ECP8+add)
+        * [.sub(Q)](#ECP8+sub)
+        * [.mul(e)](#ECP8+mul)
+    * _static_
+        * [.generator()](#ECP8.generator)
+        * [.fromBytes(b)](#ECP8.fromBytes)
+        * [.RHS(x)](#ECP8.RHS)
+        * [.mul16()](#ECP8.mul16)
+
+<a name="new_ECP8_new"></a>
+
+### new ECP8()
+Creates an instance of ECP8
+
+<a name="ECP8+is_infinity"></a>
+
+### ecP8.is\_infinity(1)
+Tests for ECP8 point equal to infinity
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| 1 | if infinity, else returns 0 |
+
+<a name="ECP8+copy"></a>
+
+### ecP8.copy(P)
+Copy ECP8 point to another ECP8 point
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | ECP8 instance |
+
+<a name="ECP8+inf"></a>
+
+### ecP8.inf()
+Set ECP8 to point-at-infinity
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+cmove"></a>
+
+### ecP8.cmove()
+conditional move of Q to P dependant on d
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+select"></a>
+
+### ecP8.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+equals"></a>
+
+### ecP8.equals(Q)
+Test P == Q
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP8 instance |
+
+<a name="ECP8+neg"></a>
+
+### ecP8.neg()
+set this=-this
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+affine"></a>
+
+### ecP8.affine()
+convert this to affine, from (x,y,z) to (x,y)
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+getX"></a>
+
+### ecP8.getX()
+extract affine x as ctx.FP2
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+getY"></a>
+
+### ecP8.getY()
+extract affine y as ctx.FP2
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+getx"></a>
+
+### ecP8.getx()
+extract projective x
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+gety"></a>
+
+### ecP8.gety()
+extract projective y
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+getz"></a>
+
+### ecP8.getz()
+extract projective z
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+toBytes"></a>
+
+### ecP8.toBytes(b)
+convert this to byte arrayextract projective x
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array output |
+
+<a name="ECP8+toString"></a>
+
+### ecP8.toString() ⇒
+convert this to hex string
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**Returns**: hex string  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+setxy"></a>
+
+### ecP8.setxy(ix, iy)
+set this=(x,y)
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+| iy | y-value |
+
+<a name="ECP8+setx"></a>
+
+### ecP8.setx(ix)
+set this=(x,.)
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| ix | x-value |
+
+<a name="ECP8+frob"></a>
+
+### ecP8.frob()
+set this*=q, where q is Modulus, using Frobenius
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+dbl"></a>
+
+### ecP8.dbl()
+this+=this
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+add"></a>
+
+### ecP8.add()
+Adds ECP8 instances
+
+param Q ECP8 instance
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8+sub"></a>
+
+### ecP8.sub(Q)
+Subtracts ECP instance Q  from this
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| Q | ECP8 instance |
+
+<a name="ECP8+mul"></a>
+
+### ecP8.mul(e)
+Multiplies an ECP8 instance P by a BIG, side-channel resistant
+
+**Kind**: instance method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG number multiplier |
+
+<a name="ECP8.generator"></a>
+
+### ECP8.generator()
+Set group generator
+
+**Kind**: static method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+<a name="ECP8.fromBytes"></a>
+
+### ECP8.fromBytes(b)
+convert from byte array to point
+
+**Kind**: static method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | input byte array |
+
+<a name="ECP8.RHS"></a>
+
+### ECP8.RHS(x)
+Calculate RHS of curve equation x^3+B
+
+**Kind**: static method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | x-value |
+
+<a name="ECP8.mul16"></a>
+
+### ECP8.mul16()
+Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3...
+
+**Kind**: static method of [<code>ECP8</code>](#ECP8)  
+**this**: <code>{ECP8}</code>  
diff --git a/docs/ff.md b/docs/ff.md
new file mode 100644
index 0000000..fa6036f
--- /dev/null
+++ b/docs/ff.md
@@ -0,0 +1,455 @@
+<a name="FF"></a>
+
+## FF
+**Kind**: global class  
+**this**: <code>{FF}</code>  
+
+* [FF](#FF)
+    * [new FF()](#new_FF_new)
+    * _instance_
+        * [.set(m)](#FF+set)
+        * [.copy(b)](#FF+copy)
+        * [.rcopy(b)](#FF+rcopy)
+        * [.dsucopy()](#FF+dsucopy)
+        * [.dscopy()](#FF+dscopy)
+        * [.sducopy()](#FF+sducopy)
+        * [.iszilch()](#FF+iszilch)
+        * [.shrw()](#FF+shrw)
+        * [.shlw()](#FF+shlw)
+        * [.parity()](#FF+parity)
+        * [.radd()](#FF+radd)
+        * [.rinc()](#FF+rinc)
+        * [.rsub()](#FF+rsub)
+        * [.rdec()](#FF+rdec)
+        * [.add()](#FF+add)
+        * [.sub()](#FF+sub)
+        * [.revsub()](#FF+revsub)
+        * [.inc()](#FF+inc)
+        * [.rnorm()](#FF+rnorm)
+        * [.shl()](#FF+shl)
+        * [.shr()](#FF+shr)
+        * [.toString()](#FF+toString)
+        * [.toBytes()](#FF+toBytes)
+        * [.karmul()](#FF+karmul)
+        * [.lmul()](#FF+lmul)
+        * [.mod()](#FF+mod)
+        * [.reduce(N, ND)](#FF+reduce) ⇒
+        * [.dmod(b)](#FF+dmod) ⇒
+        * [.invmodp()](#FF+invmodp)
+        * [.nres()](#FF+nres)
+        * [.invmod2m()](#FF+invmod2m)
+        * [.randomnum()](#FF+randomnum)
+        * [.modmul()](#FF+modmul)
+        * [.modsqr()](#FF+modsqr)
+        * [.skpow(e, p)](#FF+skpow)
+        * [.skspow(e, p)](#FF+skspow)
+        * [.power(e, p)](#FF+power)
+        * [.pow(e, p)](#FF+pow)
+        * [.pow2(e, y, f, p)](#FF+pow2)
+        * [.cfactor(s)](#FF+cfactor) ⇒
+    * _static_
+        * [.comp(a, b)](#FF.comp) ⇒
+        * [.cswap()](#FF.cswap)
+        * [.mul()](#FF.mul)
+        * [.sqr()](#FF.sqr)
+        * [.prime(p, rmg)](#FF.prime)
+
+<a name="new_FF_new"></a>
+
+### new FF()
+Creates an instance of FF.
+
+<a name="FF+set"></a>
+
+### fF.set(m)
+set to integer
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| m | Integer value to be set to |
+
+<a name="FF+copy"></a>
+
+### fF.copy(b)
+copy from FF b
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | FF element to copy from |
+
+<a name="FF+rcopy"></a>
+
+### fF.rcopy(b)
+copy from FF b
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | FF element to copy from |
+
+<a name="FF+dsucopy"></a>
+
+### fF.dsucopy()
+x=y<<n
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+dscopy"></a>
+
+### fF.dscopy()
+x=y
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+sducopy"></a>
+
+### fF.sducopy()
+x=y>>n
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+iszilch"></a>
+
+### fF.iszilch()
+test equals 0
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+shrw"></a>
+
+### fF.shrw()
+shift right by BIGBITS-bit words
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+shlw"></a>
+
+### fF.shlw()
+shift left by BIGBITS-bit words
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+parity"></a>
+
+### fF.parity()
+extract last bit
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+radd"></a>
+
+### fF.radd()
+recursive add
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+rinc"></a>
+
+### fF.rinc()
+recursive inc
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+rsub"></a>
+
+### fF.rsub()
+recursive sub
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+rdec"></a>
+
+### fF.rdec()
+recursive dec
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+add"></a>
+
+### fF.add()
+simple add
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+sub"></a>
+
+### fF.sub()
+simple sub
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+revsub"></a>
+
+### fF.revsub()
+reverse sub
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+inc"></a>
+
+### fF.inc()
+increment/decrement by a small integer
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+rnorm"></a>
+
+### fF.rnorm()
+normalise - but hold any overflow in top part unless n<0
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+shl"></a>
+
+### fF.shl()
+shift left by one bit
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+shr"></a>
+
+### fF.shr()
+shift right by one bit
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+toString"></a>
+
+### fF.toString()
+Convert to Hex String
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+toBytes"></a>
+
+### fF.toBytes()
+Convert FFs to/from byte arrays
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+karmul"></a>
+
+### fF.karmul()
+z=x*y, t is workspace
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+lmul"></a>
+
+### fF.lmul()
+return low part of product this*y
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+mod"></a>
+
+### fF.mod()
+Set b=b mod c
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+reduce"></a>
+
+### fF.reduce(N, ND) ⇒
+return this mod modulus
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**Returns**: this mod N  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| N | Mmodulus |
+| ND | Montgomery Constant |
+
+<a name="FF+dmod"></a>
+
+### fF.dmod(b) ⇒
+Reduces a double-length FF with respect to a given modulus
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**Returns**: this mod N  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | Mmodulus |
+
+<a name="FF+invmodp"></a>
+
+### fF.invmodp()
+Set return=1/this mod p. Binary method - a<p on entry
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+nres"></a>
+
+### fF.nres()
+nresidue mod m
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+invmod2m"></a>
+
+### fF.invmod2m()
+U=1/a mod 2^m - Arazi & Qi
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+randomnum"></a>
+
+### fF.randomnum()
+generate random x
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+modmul"></a>
+
+### fF.modmul()
+this*=y mod p
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+modsqr"></a>
+
+### fF.modsqr()
+this*=y mod p
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF+skpow"></a>
+
+### fF.skpow(e, p)
+this=this^e mod p using side-channel resistant Montgomery Ladder, for large e
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | exponent |
+| p | modulus |
+
+<a name="FF+skspow"></a>
+
+### fF.skspow(e, p)
+this=this^e mod p using side-channel resistant Montgomery Ladder, for short e
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | exponent |
+| p | modulus |
+
+<a name="FF+power"></a>
+
+### fF.power(e, p)
+raise to an integer power - right-to-left method
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | exponent |
+| p | modulus |
+
+<a name="FF+pow"></a>
+
+### fF.pow(e, p)
+this=this^e mod p, faster but not side channel resistant
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | exponent |
+| p | modulus |
+
+<a name="FF+pow2"></a>
+
+### fF.pow2(e, y, f, p)
+double exponentiation r=x^e.y^f mod p
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | exponent |
+| y | FF instance |
+| f | exponent |
+| p | modulus |
+
+<a name="FF+cfactor"></a>
+
+### fF.cfactor(s) ⇒
+Test if an FF has factor in common with integer s
+
+**Kind**: instance method of [<code>FF</code>](#FF)  
+**Returns**: true or false  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integerexponent |
+
+<a name="FF.comp"></a>
+
+### FF.comp(a, b) ⇒
+compare a and b - must be normalised, and of same length
+
+**Kind**: static method of [<code>FF</code>](#FF)  
+**Returns**: zero of error codetrue or false  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| a | FF number |
+| b | FF number |
+
+<a name="FF.cswap"></a>
+
+### FF.cswap()
+in-place swapping using xor - side channel resistant - lengths must be the same
+
+**Kind**: static method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF.mul"></a>
+
+### FF.mul()
+z=x*y. Assumes x and y are of same length.
+
+**Kind**: static method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF.sqr"></a>
+
+### FF.sqr()
+z=x^2
+
+**Kind**: static method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+<a name="FF.prime"></a>
+
+### FF.prime(p, rmg)
+Miller-Rabin test for primality.
+
+**Kind**: static method of [<code>FF</code>](#FF)  
+**this**: <code>{FF}</code>  
+
+| Param | Description |
+| --- | --- |
+| p | FF instance to be tested |
+| rmg | an instance of a Cryptographically Secure Random Number Generator |
+
diff --git a/docs/fp.md b/docs/fp.md
new file mode 100644
index 0000000..d3cd8fb
--- /dev/null
+++ b/docs/fp.md
@@ -0,0 +1,282 @@
+<a name="FP"></a>
+
+## FP
+**Kind**: global class  
+**this**: <code>{FP}</code>  
+
+* [FP](#FP)
+    * [new FP(x)](#new_FP_new)
+    * _instance_
+        * [.zero()](#FP+zero)
+        * [.rcopy(x)](#FP+rcopy)
+        * [.bcopy(x)](#FP+bcopy)
+        * [.copy(x)](#FP+copy)
+        * [.cswap()](#FP+cswap)
+        * [.cmove(g, d)](#FP+cmove)
+        * [.nres()](#FP+nres)
+        * [.redc()](#FP+redc)
+        * [.toString()](#FP+toString)
+        * [.iszilch()](#FP+iszilch)
+        * [.reduce()](#FP+reduce)
+        * [.one()](#FP+one)
+        * [.norm()](#FP+norm)
+        * [.mul(b)](#FP+mul)
+        * [.imul(s)](#FP+imul)
+        * [.sqr()](#FP+sqr)
+        * [.neg(x)](#FP+neg)
+        * [.sub(x)](#FP+sub)
+        * [.div2()](#FP+div2)
+        * [.fpow()](#FP+fpow)
+        * [.inverse()](#FP+inverse)
+        * [.equals(x)](#FP+equals)
+        * [.pow(e)](#FP+pow)
+        * [.jacobi()](#FP+jacobi)
+        * [.sqrt()](#FP+sqrt)
+    * _static_
+        * [.mod()](#FP.mod)
+
+<a name="new_FP_new"></a>
+
+### new FP(x)
+Creates an instance of FP.
+
+
+| Param | Description |
+| --- | --- |
+| x | FP / BIG instance |
+
+<a name="FP+zero"></a>
+
+### fP.zero()
+Set FP to zero
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+rcopy"></a>
+
+### fP.rcopy(x)
+copy from a ctx.BIG in ROM
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance to be copied |
+
+<a name="FP+bcopy"></a>
+
+### fP.bcopy(x)
+copy from another ctx.BIG
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance to be copied |
+
+<a name="FP+copy"></a>
+
+### fP.copy(x)
+Copy FP to another FP
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance to be copied |
+
+<a name="FP+cswap"></a>
+
+### fP.cswap()
+Conditional constant time swap of two FP numbers
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{BIG}</code>  
+**Parameter**: b FP number  
+**Parameter**: d Integer  
+<a name="FP+cmove"></a>
+
+### fP.cmove(g, d)
+Conditional copy of FP number
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP instance |
+| d | copy depends on this value |
+
+<a name="FP+nres"></a>
+
+### fP.nres()
+Converts from BIG integer to residue form mod Modulus
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+redc"></a>
+
+### fP.redc()
+Converts from residue form back to BIG integer form
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+toString"></a>
+
+### fP.toString()
+convert to hex string
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+iszilch"></a>
+
+### fP.iszilch()
+Tests for FP equal to zero
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+reduce"></a>
+
+### fP.reduce()
+Reduces all components of possibly unreduced FP mod Modulus
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+one"></a>
+
+### fP.one()
+Set FP to unity
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+norm"></a>
+
+### fP.norm()
+Normalises the components of an FP
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+mul"></a>
+
+### fP.mul(b)
+Fast Modular multiplication of two FPs, mod Modulus
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | FP number, the multiplier |
+
+<a name="FP+imul"></a>
+
+### fP.imul(s)
+Multiplication of an FP by a small integer
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integer |
+
+<a name="FP+sqr"></a>
+
+### fP.sqr()
+Fast Squaring of an FP
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+neg"></a>
+
+### fP.neg(x)
+negate this
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance to be set to one |
+
+<a name="FP+sub"></a>
+
+### fP.sub(x)
+subtraction of two FPs
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance |
+
+<a name="FP+div2"></a>
+
+### fP.div2()
+Divide an FP by 2
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+fpow"></a>
+
+### fP.fpow()
+return this^(p-3)/4 or this^(p-5)/8
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+inverse"></a>
+
+### fP.inverse()
+Inverting an FP
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+equals"></a>
+
+### fP.equals(x)
+Tests for equality of two FP instances
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP instance to compare |
+
+<a name="FP+pow"></a>
+
+### fP.pow(e)
+Raises an FP to the power of a BIG
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP+jacobi"></a>
+
+### fP.jacobi()
+return jacobi symbol (this/Modulus)
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP+sqrt"></a>
+
+### fP.sqrt()
+Fast Modular square root of a an FP, mod Modulus
+
+**Kind**: instance method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
+<a name="FP.mod"></a>
+
+### FP.mod()
+reduce a ctx.DBIG to a ctx.BIG using a "special" modulus
+
+**Kind**: static method of [<code>FP</code>](#FP)  
+**this**: <code>{FP}</code>  
diff --git a/docs/fp12.md b/docs/fp12.md
new file mode 100644
index 0000000..272436c
--- /dev/null
+++ b/docs/fp12.md
@@ -0,0 +1,352 @@
+<a name="FP12"></a>
+
+## FP12
+**Kind**: global class  
+**this**: <code>{FP12}</code>  
+
+* [FP12](#FP12)
+    * [new FP12()](#new_FP12_new)
+    * _instance_
+        * [.reduce()](#FP12+reduce)
+        * [.norm()](#FP12+norm)
+        * [.iszilch()](#FP12+iszilch)
+        * [.isunity()](#FP12+isunity)
+        * [.cmove(g, d)](#FP12+cmove)
+        * [.select()](#FP12+select)
+        * [.geta()](#FP12+geta)
+        * [.getb()](#FP12+getb)
+        * [.getc()](#FP12+getc)
+        * [.equals(x)](#FP12+equals)
+        * [.copy(x)](#FP12+copy)
+        * [.one(x)](#FP12+one)
+        * [.zero()](#FP12+zero)
+        * [.conj()](#FP12+conj)
+        * [.set(d, e, f)](#FP12+set)
+        * [.seta(d)](#FP12+seta)
+        * [.usqr()](#FP12+usqr)
+        * [.sqr()](#FP12+sqr)
+        * [.mul(y)](#FP12+mul)
+        * [.smul(y)](#FP12+smul)
+        * [.ssmul(y)](#FP12+ssmul)
+        * [.inverse()](#FP12+inverse)
+        * [.frob(f)](#FP12+frob)
+        * [.trace()](#FP12+trace)
+        * [.toString()](#FP12+toString)
+        * [.toBytes(w)](#FP12+toBytes)
+        * [.pow(e)](#FP12+pow)
+        * [.pinpow(e, bts)](#FP12+pinpow)
+        * [.compow(e, r)](#FP12+compow)
+    * _static_
+        * [.fromBytes(w)](#FP12.fromBytes)
+        * [.teq()](#FP12.teq)
+        * [.pow4()](#FP12.pow4)
+
+<a name="new_FP12_new"></a>
+
+### new FP12()
+Creates an instance of FP12.
+
+<a name="FP12+reduce"></a>
+
+### fP12.reduce()
+Reduces all components of possibly unreduced FP12 mod Modulus
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+norm"></a>
+
+### fP12.norm()
+Normalises the components of an FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+iszilch"></a>
+
+### fP12.iszilch()
+Tests for FP12 equal to zero
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+isunity"></a>
+
+### fP12.isunity()
+Tests for FP12 equal to unity
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+cmove"></a>
+
+### fP12.cmove(g, d)
+Conditional copy of FP12 number
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP12 instance |
+| d | copy depends on this value |
+
+<a name="FP12+select"></a>
+
+### fP12.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+geta"></a>
+
+### fP12.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+getb"></a>
+
+### fP12.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+getc"></a>
+
+### fP12.getc()
+extract c from this
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+equals"></a>
+
+### fP12.equals(x)
+Tests for equality of two FP12s
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP12 instance to compare |
+
+<a name="FP12+copy"></a>
+
+### fP12.copy(x)
+Copy FP12 to another FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP12 instance to be copied |
+
+<a name="FP12+one"></a>
+
+### fP12.one(x)
+Set FP12 to unity
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP12 instance to be set to one |
+
+<a name="FP12+zero"></a>
+
+### fP12.zero()
+Set FP12 to zero
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+conj"></a>
+
+### fP12.conj()
+Conjugation of FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+set"></a>
+
+### fP12.set(d, e, f)
+Set FP12 from three FP4 values
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | FP4 instance |
+| e | FP4 instance |
+| f | FP4 instance |
+
+<a name="FP12+seta"></a>
+
+### fP12.seta(d)
+Set FP12 from one FP4 value
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | FP4 instance |
+
+<a name="FP12+usqr"></a>
+
+### fP12.usqr()
+Fast Squaring of an FP12 in "unitary" form
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+sqr"></a>
+
+### fP12.sqr()
+Fast Squaring of an FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+mul"></a>
+
+### fP12.mul(y)
+Full unconditional Multiplication of two FP12s
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP12 instance, the multiplier |
+
+<a name="FP12+smul"></a>
+
+### fP12.smul(y)
+Fast multiplication of two sparse FP12s that arises from ATE pairing line functions
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP12 instance, the multiplier |
+
+<a name="FP12+ssmul"></a>
+
+### fP12.ssmul(y)
+Fast multiplication of what may be sparse multiplicands
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP12 instance, the multiplier |
+
+<a name="FP12+inverse"></a>
+
+### fP12.inverse()
+Inverting an FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+frob"></a>
+
+### fP12.frob(f)
+Raises an FP12 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP12+trace"></a>
+
+### fP12.trace()
+Calculate the trace of an FP12
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+toString"></a>
+
+### fP12.toString()
+convert this to hex string
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12+toBytes"></a>
+
+### fP12.toBytes(w)
+convert this to byte array
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP12+pow"></a>
+
+### fP12.pow(e)
+Raises an FP12 to the power of a BIG
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP12+pinpow"></a>
+
+### fP12.pinpow(e, bts)
+Raises an FP12 instance x to a small integer power, side-channel resistant
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | small integer exponent |
+| bts | maximum number of bits in exponent |
+
+<a name="FP12+compow"></a>
+
+### fP12.compow(e, r)
+Raises an FP12 instance to a BIG power, compressed to FP4
+
+**Kind**: instance method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG exponent |
+| r | BIG group order |
+
+<a name="FP12.fromBytes"></a>
+
+### FP12.fromBytes(w)
+convert from byte array to FP12
+
+**Kind**: static method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP12.teq"></a>
+
+### FP12.teq()
+return 1 if b==c, no branching
+
+**Kind**: static method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
+<a name="FP12.pow4"></a>
+
+### FP12.pow4()
+p=q0^u0.q1^u1.q2^u2.q3^u3
+
+**Kind**: static method of [<code>FP12</code>](#FP12)  
+**this**: <code>{FP12}</code>  
diff --git a/docs/fp16.md b/docs/fp16.md
new file mode 100644
index 0000000..0dc34b7
--- /dev/null
+++ b/docs/fp16.md
@@ -0,0 +1,386 @@
+<a name="FP16"></a>
+
+## FP16
+**Kind**: global class  
+**this**: <code>{FP16}</code>  
+
+* [FP16](#FP16)
+    * [new FP16()](#new_FP16_new)
+    * [.reduce()](#FP16+reduce)
+    * [.norm()](#FP16+norm)
+    * [.iszilch()](#FP16+iszilch)
+    * [.isunity()](#FP16+isunity)
+    * [.cmove(g, d)](#FP16+cmove)
+    * [.isreal()](#FP16+isreal)
+    * [.real()](#FP16+real)
+    * [.geta()](#FP16+geta)
+    * [.getb()](#FP16+getb)
+    * [.equals(x)](#FP16+equals)
+    * [.copy(x)](#FP16+copy)
+    * [.zero()](#FP16+zero)
+    * [.one(x)](#FP16+one)
+    * [.set(c, d)](#FP16+set)
+    * [.seta(c)](#FP16+seta)
+    * [.neg()](#FP16+neg)
+    * [.conj()](#FP16+conj)
+    * [.nconj()](#FP16+nconj)
+    * [.add(x)](#FP16+add)
+    * [.sub(x)](#FP16+sub)
+    * [.pmul(s)](#FP16+pmul)
+    * [.qmul(s)](#FP16+qmul)
+    * [.imul(s)](#FP16+imul)
+    * [.sqr()](#FP16+sqr)
+    * [.mul(y)](#FP16+mul)
+    * [.toString()](#FP16+toString)
+    * [.inverse()](#FP16+inverse)
+    * [.times_i()](#FP16+times_i)
+    * [.times_i2()](#FP16+times_i2)
+    * [.times_i4()](#FP16+times_i4)
+    * [.frob(f)](#FP16+frob)
+    * [.pow(e)](#FP16+pow)
+    * [.xtr_A(w, y, z)](#FP16+xtr_A)
+    * [.xtr_D()](#FP16+xtr_D)
+    * [.xtr_pow(n)](#FP16+xtr_pow)
+    * [.xtr_pow2()](#FP16+xtr_pow2)
+
+<a name="new_FP16_new"></a>
+
+### new FP16()
+Creates an instance of FP16.
+
+<a name="FP16+reduce"></a>
+
+### fP16.reduce()
+Reduces all components of possibly unreduced FP16 mod Modulus
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+norm"></a>
+
+### fP16.norm()
+Normalises the components of an FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+iszilch"></a>
+
+### fP16.iszilch()
+Tests for FP16 equal to zero
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+isunity"></a>
+
+### fP16.isunity()
+Tests for FP16 equal to unity
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+cmove"></a>
+
+### fP16.cmove(g, d)
+Conditional copy of FP16 number
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP16 instance |
+| d | copy depends on this value |
+
+<a name="FP16+isreal"></a>
+
+### fP16.isreal()
+test is w real? That is in a+ib test b is zero
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+real"></a>
+
+### fP16.real()
+extract real part a
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+geta"></a>
+
+### fP16.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+getb"></a>
+
+### fP16.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+equals"></a>
+
+### fP16.equals(x)
+Tests for equality of two FP16s
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP16 instance to compare |
+
+<a name="FP16+copy"></a>
+
+### fP16.copy(x)
+Copy FP16 to another FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP16 instance to be copied |
+
+<a name="FP16+zero"></a>
+
+### fP16.zero()
+Set FP16 to zero
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+one"></a>
+
+### fP16.one(x)
+Set FP16 to unity
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP16 instance to be set to one |
+
+<a name="FP16+set"></a>
+
+### fP16.set(c, d)
+Set FP16 from two FP8 values
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+| d | FP8 instance |
+
+<a name="FP16+seta"></a>
+
+### fP16.seta(c)
+Set FP16 from one FP8 value
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+
+<a name="FP16+neg"></a>
+
+### fP16.neg()
+this=-this
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+conj"></a>
+
+### fP16.conj()
+Conjugation of FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+nconj"></a>
+
+### fP16.nconj()
+Negative conjugation of FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+add"></a>
+
+### fP16.add(x)
+addition of two FP16s
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP16 instance |
+
+<a name="FP16+sub"></a>
+
+### fP16.sub(x)
+subtraction of two FP16s
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP16 instance |
+
+<a name="FP16+pmul"></a>
+
+### fP16.pmul(s)
+Multiplication of an FP16 by an FP8
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP8 instance |
+
+<a name="FP16+qmul"></a>
+
+### fP16.qmul(s)
+Multiplication of an FP16 by an FP2
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP2 instance |
+
+<a name="FP16+imul"></a>
+
+### fP16.imul(s)
+Multiplication of an FP16 by a small integer
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integer |
+
+<a name="FP16+sqr"></a>
+
+### fP16.sqr()
+Fast Squaring of an FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+mul"></a>
+
+### fP16.mul(y)
+Full unconditional Multiplication of two FP16s
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP16 instance, the multiplier |
+
+<a name="FP16+toString"></a>
+
+### fP16.toString()
+convert this to hex string
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+inverse"></a>
+
+### fP16.inverse()
+Inverting an FP16
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+times_i"></a>
+
+### fP16.times\_i()
+multiplies an FP16 instance by irreducible polynomial sqrt(1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+times_i2"></a>
+
+### fP16.times\_i2()
+multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+times_i4"></a>
+
+### fP16.times\_i4()
+multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+frob"></a>
+
+### fP16.frob(f)
+Raises an FP16 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP16+pow"></a>
+
+### fP16.pow(e)
+Raises an FP16 to the power of a BIG
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP16+xtr_A"></a>
+
+### fP16.xtr\_A(w, y, z)
+Calculates the XTR addition function r=w*x-conj(x)*y+z
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | FP16 instance |
+| y | FP16 instance |
+| z | FP16 instance |
+
+<a name="FP16+xtr_D"></a>
+
+### fP16.xtr\_D()
+Calculates the XTR doubling function r=x^2-2*conj(x)
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+<a name="FP16+xtr_pow"></a>
+
+### fP16.xtr\_pow(n)
+Calculates FP16 trace of an FP16 raised to the power of a BIG number
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Big number |
+
+<a name="FP16+xtr_pow2"></a>
+
+### fP16.xtr\_pow2()
+Calculates FP16 trace of c^a.d^b, where c and d are derived from FP16 traces of FP16s
+
+**Kind**: instance method of [<code>FP16</code>](#FP16)  
+**this**: <code>{FP16}</code>  
diff --git a/docs/fp2.md b/docs/fp2.md
new file mode 100644
index 0000000..1306e15
--- /dev/null
+++ b/docs/fp2.md
@@ -0,0 +1,349 @@
+<a name="FP2"></a>
+
+## FP2
+**Kind**: global class  
+**this**: <code>{FP2}</code>  
+
+* [FP2](#FP2)
+    * [new FP2()](#new_FP2_new)
+    * [.reduce()](#FP2+reduce)
+    * [.norm()](#FP2+norm)
+    * [.iszilch()](#FP2+iszilch)
+    * [.isunity()](#FP2+isunity)
+    * [.cmove(g, d)](#FP2+cmove)
+    * [.equals(x)](#FP2+equals)
+    * [.getA()](#FP2+getA)
+    * [.getB()](#FP2+getB)
+    * [.set(c, d)](#FP2+set)
+    * [.seta(c)](#FP2+seta)
+    * [.bset(c, d)](#FP2+bset)
+    * [.bseta(c)](#FP2+bseta)
+    * [.copy(x)](#FP2+copy)
+    * [.zero()](#FP2+zero)
+    * [.one(x)](#FP2+one)
+    * [.neg(x)](#FP2+neg)
+    * [.conj()](#FP2+conj)
+    * [.add(x)](#FP2+add)
+    * [.sub(x)](#FP2+sub)
+    * [.pmul(s)](#FP2+pmul)
+    * [.imul(s)](#FP2+imul)
+    * [.sqr()](#FP2+sqr)
+    * [.mul(y)](#FP2+mul)
+    * [.sqrt()](#FP2+sqrt) ⇒
+    * [.toString()](#FP2+toString)
+    * [.inverse()](#FP2+inverse)
+    * [.div2()](#FP2+div2)
+    * [.times_i()](#FP2+times_i)
+    * [.mul_ip()](#FP2+mul_ip)
+    * [.div_ip2()](#FP2+div_ip2)
+    * [.div_ip()](#FP2+div_ip)
+    * [.pow(e)](#FP2+pow)
+
+<a name="new_FP2_new"></a>
+
+### new FP2()
+Creates an instance of FP2.
+
+<a name="FP2+reduce"></a>
+
+### fP2.reduce()
+Reduces all components of possibly unreduced FP2 mod Modulus
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+norm"></a>
+
+### fP2.norm()
+Normalises the components of an FP2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+iszilch"></a>
+
+### fP2.iszilch()
+Tests for FP2 equal to zero
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+isunity"></a>
+
+### fP2.isunity()
+Tests for FP2 equal to unity
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+cmove"></a>
+
+### fP2.cmove(g, d)
+Conditional copy of FP2 number
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP2 instance |
+| d | copy depends on this value |
+
+<a name="FP2+equals"></a>
+
+### fP2.equals(x)
+Tests for equality of two FP2 instances
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance to compare |
+
+<a name="FP2+getA"></a>
+
+### fP2.getA()
+extract a from this
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+getB"></a>
+
+### fP2.getB()
+extract b from this
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+set"></a>
+
+### fP2.set(c, d)
+Set FP2 from two FP values
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP instance |
+| d | FP instance |
+
+<a name="FP2+seta"></a>
+
+### fP2.seta(c)
+Set FP2 from one FP value
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP instance |
+
+<a name="FP2+bset"></a>
+
+### fP2.bset(c, d)
+Set FP2 from two BIG values
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | BIG instance |
+| d | BIG instance |
+
+<a name="FP2+bseta"></a>
+
+### fP2.bseta(c)
+Set FP2 from one BIG value
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | BIG instance |
+
+<a name="FP2+copy"></a>
+
+### fP2.copy(x)
+Copy FP2 to another FP2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance to be copied |
+
+<a name="FP2+zero"></a>
+
+### fP2.zero()
+Set FP2 to zero
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+one"></a>
+
+### fP2.one(x)
+Set FP2 to unity
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance to be set to one |
+
+<a name="FP2+neg"></a>
+
+### fP2.neg(x)
+negate this
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance to be set to one |
+
+<a name="FP2+conj"></a>
+
+### fP2.conj()
+Conjugation of FP2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+add"></a>
+
+### fP2.add(x)
+addition of two FP2s
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance |
+
+<a name="FP2+sub"></a>
+
+### fP2.sub(x)
+subtraction of two FP2s
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP2 instance |
+
+<a name="FP2+pmul"></a>
+
+### fP2.pmul(s)
+Multiplication of an FP2 by an FP8
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP8 instance |
+
+<a name="FP2+imul"></a>
+
+### fP2.imul(s)
+Multiplication of an FP2 by a small integer
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integer |
+
+<a name="FP2+sqr"></a>
+
+### fP2.sqr()
+Fast Squaring of an FP2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+mul"></a>
+
+### fP2.mul(y)
+Full unconditional Multiplication of two FP2s
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP2 instance, the multiplier |
+
+<a name="FP2+sqrt"></a>
+
+### fP2.sqrt() ⇒
+sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2))
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**Returns**: true if this is QR  
+**this**: <code>{FP2}</code>  
+<a name="FP2+toString"></a>
+
+### fP2.toString()
+convert this to hex string
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+inverse"></a>
+
+### fP2.inverse()
+Inverting an FP2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+div2"></a>
+
+### fP2.div2()
+Divide an FP2 by 2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+times_i"></a>
+
+### fP2.times\_i()
+Multiply an FP2 by sqrt(-1)
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+mul_ip"></a>
+
+### fP2.mul\_ip()
+Multiply an FP2 by (1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+div_ip2"></a>
+
+### fP2.div\_ip2()
+Divide an FP2 by (1+sqrt(-1))/2
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+div_ip"></a>
+
+### fP2.div\_ip()
+Divide an FP2 by (1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+<a name="FP2+pow"></a>
+
+### fP2.pow(e)
+Raises an FP2 to the power of a BIG
+
+**Kind**: instance method of [<code>FP2</code>](#FP2)  
+**this**: <code>{FP2}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
diff --git a/docs/fp24.md b/docs/fp24.md
new file mode 100644
index 0000000..ee782c1
--- /dev/null
+++ b/docs/fp24.md
@@ -0,0 +1,352 @@
+<a name="FP24"></a>
+
+## FP24
+**Kind**: global class  
+**this**: <code>{FP24}</code>  
+
+* [FP24](#FP24)
+    * [new FP24()](#new_FP24_new)
+    * _instance_
+        * [.reduce()](#FP24+reduce)
+        * [.norm()](#FP24+norm)
+        * [.iszilch()](#FP24+iszilch)
+        * [.isunity()](#FP24+isunity)
+        * [.cmove(g, d)](#FP24+cmove)
+        * [.select()](#FP24+select)
+        * [.geta()](#FP24+geta)
+        * [.getb()](#FP24+getb)
+        * [.getc()](#FP24+getc)
+        * [.equals(x)](#FP24+equals)
+        * [.copy(x)](#FP24+copy)
+        * [.one(x)](#FP24+one)
+        * [.zero()](#FP24+zero)
+        * [.conj()](#FP24+conj)
+        * [.set(d, e, f)](#FP24+set)
+        * [.seta(c)](#FP24+seta)
+        * [.usqr()](#FP24+usqr)
+        * [.sqr()](#FP24+sqr)
+        * [.mul(y)](#FP24+mul)
+        * [.smul(y)](#FP24+smul)
+        * [.ssmul(y)](#FP24+ssmul)
+        * [.inverse()](#FP24+inverse)
+        * [.frob(f)](#FP24+frob)
+        * [.trace()](#FP24+trace)
+        * [.toString()](#FP24+toString)
+        * [.toBytes(w)](#FP24+toBytes)
+        * [.pow(e)](#FP24+pow)
+        * [.pinpow(e, bts)](#FP24+pinpow)
+        * [.compow(e, r)](#FP24+compow)
+    * _static_
+        * [.fromBytes(w)](#FP24.fromBytes)
+        * [.teq()](#FP24.teq)
+        * [.pow8()](#FP24.pow8)
+
+<a name="new_FP24_new"></a>
+
+### new FP24()
+Creates an instance of FP24.
+
+<a name="FP24+reduce"></a>
+
+### fP24.reduce()
+Reduces all components of possibly unreduced FP24 mod Modulus
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+norm"></a>
+
+### fP24.norm()
+Normalises the components of an FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+iszilch"></a>
+
+### fP24.iszilch()
+Tests for FP24 equal to zero
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+isunity"></a>
+
+### fP24.isunity()
+Tests for FP24 equal to unity
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+cmove"></a>
+
+### fP24.cmove(g, d)
+Conditional copy of FP24 number
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP24 instance |
+| d | copy depends on this value |
+
+<a name="FP24+select"></a>
+
+### fP24.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+geta"></a>
+
+### fP24.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+getb"></a>
+
+### fP24.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+getc"></a>
+
+### fP24.getc()
+extract c from this
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+equals"></a>
+
+### fP24.equals(x)
+Tests for equality of two FP24s
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP24 instance to compare |
+
+<a name="FP24+copy"></a>
+
+### fP24.copy(x)
+Copy FP24 to another FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP24 instance to be copied |
+
+<a name="FP24+one"></a>
+
+### fP24.one(x)
+Set FP24 to unity
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP24 instance to be set to one |
+
+<a name="FP24+zero"></a>
+
+### fP24.zero()
+Set FP24 to zero
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+conj"></a>
+
+### fP24.conj()
+Conjugation of FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+set"></a>
+
+### fP24.set(d, e, f)
+Set FP24 from three FP8 values
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | FP8 instance |
+| e | FP8 instance |
+| f | FP8 instance |
+
+<a name="FP24+seta"></a>
+
+### fP24.seta(c)
+Set FP24 from one FP8 value
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+
+<a name="FP24+usqr"></a>
+
+### fP24.usqr()
+Fast Squaring of an FP24 in "unitary" form
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+sqr"></a>
+
+### fP24.sqr()
+Fast Squaring of an FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+mul"></a>
+
+### fP24.mul(y)
+Full unconditional Multiplication of two FP24s
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP24 instance, the multiplier |
+
+<a name="FP24+smul"></a>
+
+### fP24.smul(y)
+Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP24 instance, the multiplier |
+
+<a name="FP24+ssmul"></a>
+
+### fP24.ssmul(y)
+Fast multiplication of what may be sparse multiplicands
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP24 instance, the multiplier |
+
+<a name="FP24+inverse"></a>
+
+### fP24.inverse()
+Inverting an FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+frob"></a>
+
+### fP24.frob(f)
+Raises an FP24 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP24+trace"></a>
+
+### fP24.trace()
+Calculate the trace of an FP24
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+toString"></a>
+
+### fP24.toString()
+convert this to hex string
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24+toBytes"></a>
+
+### fP24.toBytes(w)
+convert this to byte array
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP24+pow"></a>
+
+### fP24.pow(e)
+Raises an FP24 to the power of a BIG
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP24+pinpow"></a>
+
+### fP24.pinpow(e, bts)
+Raises an FP24 instance x to a small integer power, side-channel resistant
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | small integer exponent |
+| bts | maximum number of bits in exponent |
+
+<a name="FP24+compow"></a>
+
+### fP24.compow(e, r)
+Raises an FP24 instance to a BIG power, compressed to FP4
+
+**Kind**: instance method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG exponent |
+| r | BIG group order |
+
+<a name="FP24.fromBytes"></a>
+
+### FP24.fromBytes(w)
+convert from byte array to FP24
+
+**Kind**: static method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP24.teq"></a>
+
+### FP24.teq()
+return 1 if b==c, no branching
+
+**Kind**: static method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
+<a name="FP24.pow8"></a>
+
+### FP24.pow8()
+p=q0^u0.q1^u1.q2^u2.q3^u3...
+
+**Kind**: static method of [<code>FP24</code>](#FP24)  
+**this**: <code>{FP24}</code>  
diff --git a/docs/fp4.md b/docs/fp4.md
new file mode 100644
index 0000000..af9899c
--- /dev/null
+++ b/docs/fp4.md
@@ -0,0 +1,402 @@
+<a name="FP4"></a>
+
+## FP4
+**Kind**: global class  
+**this**: <code>{FP4}</code>  
+
+* [FP4](#FP4)
+    * [new FP4()](#new_FP4_new)
+    * [.reduce()](#FP4+reduce)
+    * [.norm()](#FP4+norm)
+    * [.iszilch()](#FP4+iszilch)
+    * [.isunity()](#FP4+isunity)
+    * [.cmove(g, d)](#FP4+cmove)
+    * [.isreal()](#FP4+isreal)
+    * [.real()](#FP4+real)
+    * [.geta()](#FP4+geta)
+    * [.getb()](#FP4+getb)
+    * [.equals(x)](#FP4+equals)
+    * [.copy(x)](#FP4+copy)
+    * [.zero()](#FP4+zero)
+    * [.one(x)](#FP4+one)
+    * [.set(c, d)](#FP4+set)
+    * [.seta(c)](#FP4+seta)
+    * [.neg()](#FP4+neg)
+    * [.conj()](#FP4+conj)
+    * [.nconj()](#FP4+nconj)
+    * [.add(x)](#FP4+add)
+    * [.sub(x)](#FP4+sub)
+    * [.pmul(s)](#FP4+pmul)
+    * [.imul(s)](#FP4+imul)
+    * [.sqr()](#FP4+sqr)
+    * [.mul(y)](#FP4+mul)
+    * [.toString()](#FP4+toString)
+    * [.inverse()](#FP4+inverse)
+    * [.times_i()](#FP4+times_i)
+    * [.frob(f)](#FP4+frob)
+    * [.pow(e)](#FP4+pow)
+    * [.xtr_A(w, y, z)](#FP4+xtr_A)
+    * [.xtr_D()](#FP4+xtr_D)
+    * [.xtr_pow(n)](#FP4+xtr_pow)
+    * [.xtr_pow2()](#FP4+xtr_pow2)
+    * [.div2()](#FP4+div2)
+    * [.div_i()](#FP4+div_i)
+    * [.div_2i()](#FP4+div_2i)
+    * [.qmul(s)](#FP4+qmul)
+    * [.sqrt()](#FP4+sqrt)
+
+<a name="new_FP4_new"></a>
+
+### new FP4()
+Creates an instance of FP4
+
+<a name="FP4+reduce"></a>
+
+### fP4.reduce()
+Reduces all components of possibly unreduced FP4 mod Modulus
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+norm"></a>
+
+### fP4.norm()
+Normalises the components of an FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+iszilch"></a>
+
+### fP4.iszilch()
+Tests for FP4 equal to zero
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+isunity"></a>
+
+### fP4.isunity()
+Tests for FP4 equal to unity
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+cmove"></a>
+
+### fP4.cmove(g, d)
+Conditional copy of FP4 number
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP4 instance |
+| d | copy depends on this value |
+
+<a name="FP4+isreal"></a>
+
+### fP4.isreal()
+test is w real? That is in a+ib test b is zero
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+real"></a>
+
+### fP4.real()
+extract real part a
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+geta"></a>
+
+### fP4.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+getb"></a>
+
+### fP4.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+equals"></a>
+
+### fP4.equals(x)
+Tests for equality of two FP4s
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP4 instance to compare |
+
+<a name="FP4+copy"></a>
+
+### fP4.copy(x)
+Copy FP4 to another FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP4 instance to be copied |
+
+<a name="FP4+zero"></a>
+
+### fP4.zero()
+Set FP4 to zero
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+one"></a>
+
+### fP4.one(x)
+Set FP4 to unity
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP4 instance to be set to one |
+
+<a name="FP4+set"></a>
+
+### fP4.set(c, d)
+Set FP4 from two FP2 values
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP2 instance |
+| d | FP2 instance |
+
+<a name="FP4+seta"></a>
+
+### fP4.seta(c)
+Set FP4 from one FP2 value
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP2 instance |
+
+<a name="FP4+neg"></a>
+
+### fP4.neg()
+Negation of FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+conj"></a>
+
+### fP4.conj()
+Conjugation of FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+nconj"></a>
+
+### fP4.nconj()
+Negative conjugation of FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+add"></a>
+
+### fP4.add(x)
+addition of two FP4s
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP4 instance |
+
+<a name="FP4+sub"></a>
+
+### fP4.sub(x)
+subtraction of two FP4s
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP4 instance |
+
+<a name="FP4+pmul"></a>
+
+### fP4.pmul(s)
+Multiplication of an FP4 by an FP8
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP8 instance |
+
+<a name="FP4+imul"></a>
+
+### fP4.imul(s)
+Multiplication of an FP4 by an integer
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integer multiplier |
+
+<a name="FP4+sqr"></a>
+
+### fP4.sqr()
+Fast Squaring of an FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+mul"></a>
+
+### fP4.mul(y)
+Full unconditional Multiplication of two FP4s
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP4 instance, the multiplier |
+
+<a name="FP4+toString"></a>
+
+### fP4.toString()
+convert to hex string
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+inverse"></a>
+
+### fP4.inverse()
+Inverting an FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+times_i"></a>
+
+### fP4.times\_i()
+multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+frob"></a>
+
+### fP4.frob(f)
+Raises an FP4 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP4+pow"></a>
+
+### fP4.pow(e)
+Raises an FP4 to the power of a BIG
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP4+xtr_A"></a>
+
+### fP4.xtr\_A(w, y, z)
+Calculates the XTR addition function r=w*x-conj(x)*y+z
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | FP4 instance |
+| y | FP4 instance |
+| z | FP4 instance |
+
+<a name="FP4+xtr_D"></a>
+
+### fP4.xtr\_D()
+Calculates the XTR doubling function r=x^2-2*conj(x)
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+xtr_pow"></a>
+
+### fP4.xtr\_pow(n)
+Calculates FP4 trace of an FP4 raised to the power of a BIG number
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Big number |
+
+<a name="FP4+xtr_pow2"></a>
+
+### fP4.xtr\_pow2()
+Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP4s
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+div2"></a>
+
+### fP4.div2()
+Divide an FP4 by 2
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+div_i"></a>
+
+### fP4.div\_i()
+Divide FP4 number by QNR
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+div_2i"></a>
+
+### fP4.div\_2i()
+Divide an FP4 by QNR/2
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+<a name="FP4+qmul"></a>
+
+### fP4.qmul(s)
+Multiplication of an FP4 by an FP
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP multiplier |
+
+<a name="FP4+sqrt"></a>
+
+### fP4.sqrt()
+Calculate square root of an FP4
+
+**Kind**: instance method of [<code>FP4</code>](#FP4)  
+**this**: <code>{FP4}</code>  
diff --git a/docs/fp48.md b/docs/fp48.md
new file mode 100644
index 0000000..ba6fe67
--- /dev/null
+++ b/docs/fp48.md
@@ -0,0 +1,352 @@
+<a name="FP48"></a>
+
+## FP48
+**Kind**: global class  
+**this**: <code>{FP48}</code>  
+
+* [FP48](#FP48)
+    * [new FP48()](#new_FP48_new)
+    * _instance_
+        * [.reduce()](#FP48+reduce)
+        * [.norm()](#FP48+norm)
+        * [.iszilch()](#FP48+iszilch)
+        * [.isunity()](#FP48+isunity)
+        * [.cmove(g, d)](#FP48+cmove)
+        * [.select()](#FP48+select)
+        * [.geta()](#FP48+geta)
+        * [.getb()](#FP48+getb)
+        * [.getc()](#FP48+getc)
+        * [.equals(x)](#FP48+equals)
+        * [.copy(x)](#FP48+copy)
+        * [.one(x)](#FP48+one)
+        * [.zero()](#FP48+zero)
+        * [.conj()](#FP48+conj)
+        * [.set(d, e, f)](#FP48+set)
+        * [.seta(c)](#FP48+seta)
+        * [.usqr()](#FP48+usqr)
+        * [.sqr()](#FP48+sqr)
+        * [.mul(y)](#FP48+mul)
+        * [.smul(y)](#FP48+smul)
+        * [.ssmul(y)](#FP48+ssmul)
+        * [.inverse()](#FP48+inverse)
+        * [.frob(f)](#FP48+frob)
+        * [.trace()](#FP48+trace)
+        * [.toString()](#FP48+toString)
+        * [.toBytes(w)](#FP48+toBytes)
+        * [.pow(e)](#FP48+pow)
+        * [.pinpow(e, bts)](#FP48+pinpow)
+        * [.compow(e, r)](#FP48+compow)
+    * _static_
+        * [.fromBytes(w)](#FP48.fromBytes)
+        * [.teq()](#FP48.teq)
+        * [.pow16()](#FP48.pow16)
+
+<a name="new_FP48_new"></a>
+
+### new FP48()
+Creates an instance of FP48.
+
+<a name="FP48+reduce"></a>
+
+### fP48.reduce()
+Reduces all components of possibly unreduced FP48 mod Modulus
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+norm"></a>
+
+### fP48.norm()
+Normalises the components of an FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+iszilch"></a>
+
+### fP48.iszilch()
+Tests for FP48 equal to zero
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+isunity"></a>
+
+### fP48.isunity()
+Tests for FP48 equal to unity
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+cmove"></a>
+
+### fP48.cmove(g, d)
+Conditional copy of FP48 number
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP48 instance |
+| d | copy depends on this value |
+
+<a name="FP48+select"></a>
+
+### fP48.select()
+Constant time select from pre-computed table
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+geta"></a>
+
+### fP48.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+getb"></a>
+
+### fP48.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+getc"></a>
+
+### fP48.getc()
+extract c from this
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+equals"></a>
+
+### fP48.equals(x)
+Tests for equality of two FP48s
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP48 instance to compare |
+
+<a name="FP48+copy"></a>
+
+### fP48.copy(x)
+Copy FP48 to another FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP48 instance to be copied |
+
+<a name="FP48+one"></a>
+
+### fP48.one(x)
+Set FP48 to unity
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP48 instance to be set to one |
+
+<a name="FP48+zero"></a>
+
+### fP48.zero()
+Set FP48 to zero
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+conj"></a>
+
+### fP48.conj()
+Conjugation of FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+set"></a>
+
+### fP48.set(d, e, f)
+Set FP48 from three FP16 values
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | FP16 instance |
+| e | FP16 instance |
+| f | FP16 instance |
+
+<a name="FP48+seta"></a>
+
+### fP48.seta(c)
+Set FP48 from one FP16 value
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP16 instance |
+
+<a name="FP48+usqr"></a>
+
+### fP48.usqr()
+Fast Squaring of an FP48 in "unitary" form
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+sqr"></a>
+
+### fP48.sqr()
+Fast Squaring of an FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+mul"></a>
+
+### fP48.mul(y)
+Full unconditional Multiplication of two FP48s
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP48 instance, the multiplier |
+
+<a name="FP48+smul"></a>
+
+### fP48.smul(y)
+Fast multiplication of two sparse FP48s that arises from ATE pairing line functions
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP48 instance, the multiplier |
+
+<a name="FP48+ssmul"></a>
+
+### fP48.ssmul(y)
+Fast multiplication of what may be sparse multiplicands
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP48 instance, the multiplier |
+
+<a name="FP48+inverse"></a>
+
+### fP48.inverse()
+Inverting an FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+frob"></a>
+
+### fP48.frob(f)
+Raises an FP48 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP48+trace"></a>
+
+### fP48.trace()
+Calculate the trace of an FP48
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+toString"></a>
+
+### fP48.toString()
+convert this to hex string
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48+toBytes"></a>
+
+### fP48.toBytes(w)
+convert this to byte array
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP48+pow"></a>
+
+### fP48.pow(e)
+Raises an FP48 to the power of a BIG
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP48+pinpow"></a>
+
+### fP48.pinpow(e, bts)
+Raises an FP48 instance x to a small integer power, side-channel resistant
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | small integer exponent |
+| bts | maximum number of bits in exponent |
+
+<a name="FP48+compow"></a>
+
+### fP48.compow(e, r)
+Raises an FP48 instance to a BIG power, compressed to FP4
+
+**Kind**: instance method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG exponent |
+| r | BIG group order |
+
+<a name="FP48.fromBytes"></a>
+
+### FP48.fromBytes(w)
+convert from byte array to FP48
+
+**Kind**: static method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | Byte array |
+
+<a name="FP48.teq"></a>
+
+### FP48.teq()
+return 1 if b==c, no branching
+
+**Kind**: static method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
+<a name="FP48.pow16"></a>
+
+### FP48.pow16()
+p=q0^u0.q1^u1.q2^u2.q3^u3...
+
+**Kind**: static method of [<code>FP48</code>](#FP48)  
+**this**: <code>{FP48}</code>  
diff --git a/docs/fp8.md b/docs/fp8.md
new file mode 100644
index 0000000..0e22037
--- /dev/null
+++ b/docs/fp8.md
@@ -0,0 +1,437 @@
+<a name="FP8"></a>
+
+## FP8
+**Kind**: global class  
+**this**: <code>{FP4}</code>  
+
+* [FP8](#FP8)
+    * [new FP8(c, d)](#new_FP8_new)
+    * [.reduce()](#FP8+reduce)
+    * [.norm()](#FP8+norm)
+    * [.iszilch()](#FP8+iszilch)
+    * [.isunity()](#FP8+isunity)
+    * [.cmove(g, d)](#FP8+cmove)
+    * [.isreal()](#FP8+isreal)
+    * [.real()](#FP8+real)
+    * [.geta()](#FP8+geta)
+    * [.getb()](#FP8+getb)
+    * [.equals(x)](#FP8+equals)
+    * [.copy(x)](#FP8+copy)
+    * [.zero()](#FP8+zero)
+    * [.one(x)](#FP8+one)
+    * [.set(c, d)](#FP8+set)
+    * [.seta(c)](#FP8+seta)
+    * [.neg()](#FP8+neg)
+    * [.conj()](#FP8+conj)
+    * [.nconj()](#FP8+nconj)
+    * [.add(x)](#FP8+add)
+    * [.sub(x)](#FP8+sub)
+    * [.pmul(s)](#FP8+pmul)
+    * [.imul(s)](#FP8+imul)
+    * [.sqr()](#FP8+sqr)
+    * [.mul(y)](#FP8+mul)
+    * [.toString()](#FP8+toString)
+    * [.inverse()](#FP8+inverse)
+    * [.times_i()](#FP8+times_i)
+    * [.times_i2()](#FP8+times_i2)
+    * [.frob(f)](#FP8+frob)
+    * [.pow(e)](#FP8+pow)
+    * [.xtr_A(w, y, z)](#FP8+xtr_A)
+    * [.xtr_D()](#FP8+xtr_D)
+    * [.xtr_pow(n)](#FP8+xtr_pow)
+    * [.xtr_pow2()](#FP8+xtr_pow2)
+    * [.div2()](#FP8+div2)
+    * [.div_i()](#FP8+div_i)
+    * [.div_i2()](#FP8+div_i2)
+    * [.div_2i()](#FP8+div_2i)
+    * [.qmul(s)](#FP8+qmul)
+    * [.tmul(s)](#FP8+tmul)
+    * [.sqrt()](#FP8+sqrt)
+
+<a name="new_FP8_new"></a>
+
+### new FP8(c, d)
+Creates an instance of FP8
+
+
+| Param | Description |
+| --- | --- |
+| c | FP8 / FP4 instance |
+| d | FP4 instance |
+
+<a name="FP8+reduce"></a>
+
+### fP8.reduce()
+Reduces all components of possibly unreduced FP8 mod Modulus
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+norm"></a>
+
+### fP8.norm()
+Normalises the components of an FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+iszilch"></a>
+
+### fP8.iszilch()
+Tests for FP8 equal to zero
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+isunity"></a>
+
+### fP8.isunity()
+Tests for FP8 equal to unity
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+cmove"></a>
+
+### fP8.cmove(g, d)
+Conditional copy of FP8 number
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| g | FP8 instance |
+| d | copy depends on this value |
+
+<a name="FP8+isreal"></a>
+
+### fP8.isreal()
+test is w real? That is in a+ib test b is zero
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+real"></a>
+
+### fP8.real()
+extract real part a
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+geta"></a>
+
+### fP8.geta()
+extract a from this
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+getb"></a>
+
+### fP8.getb()
+extract b from this
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+equals"></a>
+
+### fP8.equals(x)
+Tests for equality of two FP8s
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP8 instance to compare |
+
+<a name="FP8+copy"></a>
+
+### fP8.copy(x)
+Copy FP8 to another FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP8 instance to be copied |
+
+<a name="FP8+zero"></a>
+
+### fP8.zero()
+Set FP8 to zero
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+one"></a>
+
+### fP8.one(x)
+Set FP8 to unity
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP8 instance to be set to one |
+
+<a name="FP8+set"></a>
+
+### fP8.set(c, d)
+Set FP8 from two FP4 values
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP4 instance |
+| d | FP4 instance |
+
+<a name="FP8+seta"></a>
+
+### fP8.seta(c)
+Set FP8 from one FP4 value
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP4 instance |
+
+<a name="FP8+neg"></a>
+
+### fP8.neg()
+Negation of FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+conj"></a>
+
+### fP8.conj()
+Conjugation of FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+nconj"></a>
+
+### fP8.nconj()
+Negative conjugation of FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+add"></a>
+
+### fP8.add(x)
+addition of two FP8s
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP8 instance |
+
+<a name="FP8+sub"></a>
+
+### fP8.sub(x)
+subtraction of two FP8s
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| x | FP8 instance |
+
+<a name="FP8+pmul"></a>
+
+### fP8.pmul(s)
+Multiplication of an FP8 by an FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP8 instance |
+
+<a name="FP8+imul"></a>
+
+### fP8.imul(s)
+Multiplication of an FP8 by a small integer
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | integer |
+
+<a name="FP8+sqr"></a>
+
+### fP8.sqr()
+Fast Squaring of an FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+mul"></a>
+
+### fP8.mul(y)
+Full unconditional Multiplication of two FP8s
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | FP8 instance, the multiplier |
+
+<a name="FP8+toString"></a>
+
+### fP8.toString()
+convert to hex string
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+inverse"></a>
+
+### fP8.inverse()
+Inverting an FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+times_i"></a>
+
+### fP8.times\_i()
+multiplies an FP8 instance by irreducible polynomial sqrt(1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+times_i2"></a>
+
+### fP8.times\_i2()
+multiplies an FP8 instance by irreducible polynomial (1+sqrt(-1))
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+frob"></a>
+
+### fP8.frob(f)
+Raises an FP8 to the power of the internal modulus p, using the Frobenius
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| f | Modulus |
+
+<a name="FP8+pow"></a>
+
+### fP8.pow(e)
+Raises an FP8 to the power of a BIG
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| e | BIG instance exponent |
+
+<a name="FP8+xtr_A"></a>
+
+### fP8.xtr\_A(w, y, z)
+Calculates the XTR addition function r=w*x-conj(x)*y+z
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| w | FP8 instance |
+| y | FP8 instance |
+| z | FP8 instance |
+
+<a name="FP8+xtr_D"></a>
+
+### fP8.xtr\_D()
+Calculates the XTR doubling function r=x^2-2*conj(x)
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+xtr_pow"></a>
+
+### fP8.xtr\_pow(n)
+Calculates FP8 trace of an FP8 raised to the power of a BIG number
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Big number |
+
+<a name="FP8+xtr_pow2"></a>
+
+### fP8.xtr\_pow2()
+Calculates FP8 trace of c^a.d^b, where c and d are derived from FP8 traces of FP8s
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+div2"></a>
+
+### fP8.div2()
+Divide an FP8 by 2
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+div_i"></a>
+
+### fP8.div\_i()
+Divide FP8 number by QNR
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+div_i2"></a>
+
+### fP8.div\_i2()
+Divide an FP8 by QNR twice
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+div_2i"></a>
+
+### fP8.div\_2i()
+Divide an FP8 by QNR/2
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+<a name="FP8+qmul"></a>
+
+### fP8.qmul(s)
+Multiplication of an FP8 by an FP2
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP2 multiplier |
+
+<a name="FP8+tmul"></a>
+
+### fP8.tmul(s)
+Multiplication of an FP8 by an FP
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | FP multiplier |
+
+<a name="FP8+sqrt"></a>
+
+### fP8.sqrt()
+Calculate square root of an FP8
+
+**Kind**: instance method of [<code>FP8</code>](#FP8)  
+**this**: <code>{FP8}</code>  
diff --git a/docs/gcm.md b/docs/gcm.md
new file mode 100644
index 0000000..55e3954
--- /dev/null
+++ b/docs/gcm.md
@@ -0,0 +1,74 @@
+<a name="GCM"></a>
+
+## GCM
+**Kind**: global class  
+**this**: <code>{GCM}</code>  
+
+* [GCM](#GCM)
+    * [new GCM()](#new_GCM_new)
+    * [.init(nk, key, niv, iv)](#GCM+init)
+    * [.add_header(header, len)](#GCM+add_header)
+    * [.add_plain(plain, len)](#GCM+add_plain) ⇒
+    * [.add_cipher(cipher, len)](#GCM+add_cipher) ⇒
+
+<a name="new_GCM_new"></a>
+
+### new GCM()
+Creates an instance of GCM
+
+<a name="GCM+init"></a>
+
+### gcM.init(nk, key, niv, iv)
+Initialize GCM mode
+
+**Kind**: instance method of [<code>GCM</code>](#GCM)  
+**this**: <code>{GCM}</code>  
+
+| Param | Description |
+| --- | --- |
+| nk | is the key length in bytes, 16, 24 or 32 |
+| key | the AES key as an array of 16 bytes |
+| niv | the number of bytes in the Initialisation Vector (IV) |
+| iv | the IV |
+
+<a name="GCM+add_header"></a>
+
+### gcM.add\_header(header, len)
+Add header (material to be authenticated but not encrypted)
+
+**Kind**: instance method of [<code>GCM</code>](#GCM)  
+**this**: <code>{GCM}</code>  
+
+| Param | Description |
+| --- | --- |
+| header | is the header material to be added |
+| len | the number of bytes in the header |
+
+<a name="GCM+add_plain"></a>
+
+### gcM.add\_plain(plain, len) ⇒
+Add plaintext and extract ciphertext
+
+**Kind**: instance method of [<code>GCM</code>](#GCM)  
+**Returns**: cipher is the ciphertext generated  
+**this**: <code>{GCM}</code>  
+
+| Param | Description |
+| --- | --- |
+| plain | is the plaintext material to be added |
+| len | the number of bytes in the plaintext |
+
+<a name="GCM+add_cipher"></a>
+
+### gcM.add\_cipher(cipher, len) ⇒
+Add Ciphertext - decrypts to plaintext
+
+**Kind**: instance method of [<code>GCM</code>](#GCM)  
+**Returns**: plain is the plaintext material generated  
+**this**: <code>{GCM}</code>  
+
+| Param | Description |
+| --- | --- |
+| cipher | is the ciphertext to be added |
+| len | the number of bytes in the plaintext |
+
diff --git a/docs/hash256.md b/docs/hash256.md
new file mode 100644
index 0000000..e2d8f14
--- /dev/null
+++ b/docs/hash256.md
@@ -0,0 +1,70 @@
+<a name="HASH256"></a>
+
+## HASH256
+**Kind**: global class  
+**this**: <code>{HASH256}</code>  
+
+* [HASH256](#HASH256)
+    * [new HASH256()](#new_HASH256_new)
+    * [.init()](#HASH256+init)
+    * [.process(byt)](#HASH256+process)
+    * [.process_array(b)](#HASH256+process_array)
+    * [.process_num(n)](#HASH256+process_num)
+    * [.hash()](#HASH256+hash) ⇒
+
+<a name="new_HASH256_new"></a>
+
+### new HASH256()
+Creates an instance of HASH256
+
+<a name="HASH256+init"></a>
+
+### hasH256.init()
+Initialise Hash function
+
+**Kind**: instance method of [<code>HASH256</code>](#HASH256)  
+**this**: <code>{HASH256}</code>  
+<a name="HASH256+process"></a>
+
+### hasH256.process(byt)
+Process a single byte
+
+**Kind**: instance method of [<code>HASH256</code>](#HASH256)  
+**this**: <code>{HASH256}</code>  
+
+| Param | Description |
+| --- | --- |
+| byt | byte to be included in hash |
+
+<a name="HASH256+process_array"></a>
+
+### hasH256.process\_array(b)
+Process an array of bytes
+
+**Kind**: instance method of [<code>HASH256</code>](#HASH256)  
+**this**: <code>{HASH256}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte arrray to be included in hash |
+
+<a name="HASH256+process_num"></a>
+
+### hasH256.process\_num(n)
+Process a 32-bit integer
+
+**Kind**: instance method of [<code>HASH256</code>](#HASH256)  
+**this**: <code>{HASH256}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Integer to be included in hash |
+
+<a name="HASH256+hash"></a>
+
+### hasH256.hash() ⇒
+Generate 32-byte hash
+
+**Kind**: instance method of [<code>HASH256</code>](#HASH256)  
+**Returns**: digest 32-byte hash  
+**this**: <code>{HASH256}</code>  
diff --git a/docs/hash384.md b/docs/hash384.md
new file mode 100644
index 0000000..3d51da9
--- /dev/null
+++ b/docs/hash384.md
@@ -0,0 +1,70 @@
+<a name="HASH384"></a>
+
+## HASH384
+**Kind**: global class  
+**this**: <code>{HASH384}</code>  
+
+* [HASH384](#HASH384)
+    * [new HASH384()](#new_HASH384_new)
+    * [.init()](#HASH384+init)
+    * [.process(byt)](#HASH384+process)
+    * [.process_array(b)](#HASH384+process_array)
+    * [.process_num(n)](#HASH384+process_num)
+    * [.hash()](#HASH384+hash) ⇒
+
+<a name="new_HASH384_new"></a>
+
+### new HASH384()
+Creates an instance of HASH384
+
+<a name="HASH384+init"></a>
+
+### hasH384.init()
+Initialise Hash function
+
+**Kind**: instance method of [<code>HASH384</code>](#HASH384)  
+**this**: <code>{HASH384}</code>  
+<a name="HASH384+process"></a>
+
+### hasH384.process(byt)
+Process a single byte
+
+**Kind**: instance method of [<code>HASH384</code>](#HASH384)  
+**this**: <code>{HASH384}</code>  
+
+| Param | Description |
+| --- | --- |
+| byt | byte to be included in hash |
+
+<a name="HASH384+process_array"></a>
+
+### hasH384.process\_array(b)
+Process an array of bytes
+
+**Kind**: instance method of [<code>HASH384</code>](#HASH384)  
+**this**: <code>{HASH384}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte arrray to be included in hash |
+
+<a name="HASH384+process_num"></a>
+
+### hasH384.process\_num(n)
+Process a 32-bit integer
+
+**Kind**: instance method of [<code>HASH384</code>](#HASH384)  
+**this**: <code>{HASH384}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Integer to be included in hash |
+
+<a name="HASH384+hash"></a>
+
+### hasH384.hash() ⇒
+Generate 32-byte hash
+
+**Kind**: instance method of [<code>HASH384</code>](#HASH384)  
+**Returns**: digest 32-byte hash  
+**this**: <code>{HASH384}</code>  
diff --git a/docs/hash512.md b/docs/hash512.md
new file mode 100644
index 0000000..8e7f0f7
--- /dev/null
+++ b/docs/hash512.md
@@ -0,0 +1,70 @@
+<a name="HASH512"></a>
+
+## HASH512
+**Kind**: global class  
+**this**: <code>{HASH512}</code>  
+
+* [HASH512](#HASH512)
+    * [new HASH512()](#new_HASH512_new)
+    * [.init()](#HASH512+init)
+    * [.process(byt)](#HASH512+process)
+    * [.process_array(b)](#HASH512+process_array)
+    * [.process_num(n)](#HASH512+process_num)
+    * [.hash()](#HASH512+hash) ⇒
+
+<a name="new_HASH512_new"></a>
+
+### new HASH512()
+Creates an instance of HASH512
+
+<a name="HASH512+init"></a>
+
+### hasH512.init()
+Initialise Hash function
+
+**Kind**: instance method of [<code>HASH512</code>](#HASH512)  
+**this**: <code>{HASH512}</code>  
+<a name="HASH512+process"></a>
+
+### hasH512.process(byt)
+Process a single byte
+
+**Kind**: instance method of [<code>HASH512</code>](#HASH512)  
+**this**: <code>{HASH512}</code>  
+
+| Param | Description |
+| --- | --- |
+| byt | byte to be included in hash |
+
+<a name="HASH512+process_array"></a>
+
+### hasH512.process\_array(b)
+Process an array of bytes
+
+**Kind**: instance method of [<code>HASH512</code>](#HASH512)  
+**this**: <code>{HASH512}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte arrray to be included in hash |
+
+<a name="HASH512+process_num"></a>
+
+### hasH512.process\_num(n)
+Process a 32-bit integer
+
+**Kind**: instance method of [<code>HASH512</code>](#HASH512)  
+**this**: <code>{HASH512}</code>  
+
+| Param | Description |
+| --- | --- |
+| n | Integer to be included in hash |
+
+<a name="HASH512+hash"></a>
+
+### hasH512.hash() ⇒
+Generate 32-byte hash
+
+**Kind**: instance method of [<code>HASH512</code>](#HASH512)  
+**Returns**: digest 32-byte hash  
+**this**: <code>{HASH512}</code>  
diff --git a/docs/mpin.md b/docs/mpin.md
new file mode 100644
index 0000000..fa5e065
--- /dev/null
+++ b/docs/mpin.md
@@ -0,0 +1,573 @@
+<a name="MPIN"></a>
+
+## MPIN
+**Kind**: global class  
+**this**: <code>{MPIN}</code>  
+
+* [MPIN](#MPIN)
+    * [new MPIN()](#new_MPIN_new)
+    * [.today()](#MPIN.today) ⇒
+    * [.bytestostring(b)](#MPIN.bytestostring) ⇒
+    * [.stringtobytes(s)](#MPIN.stringtobytes) ⇒
+    * [.comparebytes(a, b)](#MPIN.comparebytes) ⇒
+    * [.mpin_hash(c, U)](#MPIN.mpin_hash) ⇒
+    * [.hashit(sha, n, B)](#MPIN.hashit) ⇒
+    * [.map(u, cb)](#MPIN.map) ⇒
+    * [.unmap(u, P)](#MPIN.unmap) ⇒
+    * [.RECOMBINE_G1(R1, R2, R)](#MPIN.RECOMBINE_G1) ⇒
+    * [.RECOMBINE_G2(W1, W2, W)](#MPIN.RECOMBINE_G2) ⇒
+    * [.HASH_ID(sha, ID)](#MPIN.HASH_ID) ⇒
+    * [.RANDOM_GENERATE(rng, S)](#MPIN.RANDOM_GENERATE) ⇒
+    * [.EXTRACT_PIN()](#MPIN.EXTRACT_PIN) ⇒
+    * [.EXTRACT_FACTOR()](#MPIN.EXTRACT_FACTOR) ⇒
+    * [.RESTORE_FACTOR()](#MPIN.RESTORE_FACTOR) ⇒
+    * [.GET_SERVER_SECRET(S, SST)](#MPIN.GET_SERVER_SECRET) ⇒
+    * [.GET_G1_MULTIPLE(type, x, G, W)](#MPIN.GET_G1_MULTIPLE) ⇒
+    * [.GET_CLIENT_SECRET(S, CID, CST)](#MPIN.GET_CLIENT_SECRET) ⇒
+    * [.GET_CLIENT_PERMIT(sha, date, S, CID, CTT)](#MPIN.GET_CLIENT_PERMIT) ⇒
+    * [.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT)](#MPIN.CLIENT_1) ⇒
+    * [.CLIENT_2(X, Y, SEC)](#MPIN.CLIENT_2) ⇒
+    * [.SERVER_1(sha, date, CID, HID, HTID)](#MPIN.SERVER_1) ⇒
+    * [.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa)](#MPIN.SERVER_2) ⇒
+    * [.KANGAROO(E, F)](#MPIN.KANGAROO) ⇒
+    * [.GET_TIME()](#MPIN.GET_TIME) ⇒
+    * [.GET_Y(sha, TimeValue, xCID, Y)](#MPIN.GET_Y) ⇒
+    * [.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message)](#MPIN.CLIENT) ⇒
+    * [.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa)](#MPIN.SERVER) ⇒
+    * [.PRECOMPUTE(TOKEN, CID, G1, G2)](#MPIN.PRECOMPUTE) ⇒
+    * [.HASH_ALL(sha, HID, xID, xCID, SEC, Y, R, W)](#MPIN.HASH_ALL) ⇒
+    * [.CLIENT_KEY(sha, G1, G2, pin, R, X, H, wCID, CK)](#MPIN.CLIENT_KEY) ⇒
+    * [.SERVER_KEY(h, Z, SST, W, H, HID, xID, xCID, SK)](#MPIN.SERVER_KEY) ⇒
+    * [.GET_DVS_KEYPAIR(rng, Z, Pa)](#MPIN.GET_DVS_KEYPAIR) ⇒
+
+<a name="new_MPIN_new"></a>
+
+### new MPIN()
+Creates an instance of MPIN
+
+<a name="MPIN.today"></a>
+
+### MPIN.today() ⇒
+Get epoch time for today
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: time in slots since epoch  
+**this**: <code>{MPIN}</code>  
+<a name="MPIN.bytestostring"></a>
+
+### MPIN.bytestostring(b) ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: s string  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array |
+
+<a name="MPIN.stringtobytes"></a>
+
+### MPIN.stringtobytes(s) ⇒
+Convert a string to byte array
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: b byte array  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | string |
+
+<a name="MPIN.comparebytes"></a>
+
+### MPIN.comparebytes(a, b) ⇒
+Convert byte arrays
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: true if equal  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| a | byte array |
+| b | byte array |
+
+<a name="MPIN.mpin_hash"></a>
+
+### MPIN.mpin\_hash(c, U) ⇒
+Hash values
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: R hash value  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+| U | ECP unstancebyte array |
+
+<a name="MPIN.hashit"></a>
+
+### MPIN.hashit(sha, n, B) ⇒
+General purpose hash function
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: R hash value  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| n | Integer |
+| B | byte array |
+
+<a name="MPIN.map"></a>
+
+### MPIN.map(u, cb) ⇒
+maps a random u to a point on the curve
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: P ECP pointhash value  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| cb | an integer representing the "sign" of y, in fact its least significant bit. |
+
+<a name="MPIN.unmap"></a>
+
+### MPIN.unmap(u, P) ⇒
+returns u derived from P. Random value in range 1 to return value should then be added to u
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: r Value that should be added to u to derive P  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| P | ECP pointhash value |
+
+<a name="MPIN.RECOMBINE_G1"></a>
+
+### MPIN.RECOMBINE\_G1(R1, R2, R) ⇒
+Add two members from the group G1
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| R1 | Input member of G1 |
+| R2 | Input member of G1 |
+| R | Output member of G1. R=R1+R2 |
+
+<a name="MPIN.RECOMBINE_G2"></a>
+
+### MPIN.RECOMBINE\_G2(W1, W2, W) ⇒
+Add two members from the group G2
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| W1 | Input member of G2 |
+| W2 | Input member of G2 |
+| W | Output member of G2. W=W1+W2 |
+
+<a name="MPIN.HASH_ID"></a>
+
+### MPIN.HASH\_ID(sha, ID) ⇒
+Hash the identity
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: hash value  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| ID | Identity as byte array |
+
+<a name="MPIN.RANDOM_GENERATE"></a>
+
+### MPIN.RANDOM\_GENERATE(rng, S) ⇒
+Create random secret
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| S | Random secret value |
+
+<a name="MPIN.EXTRACT_PIN"></a>
+
+### MPIN.EXTRACT\_PIN() ⇒
+Extract a PIN number from a client secret
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: token  
+**this**: <code>{MPIN}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: pin PIN value  
+**Parameter**: TOKEN Client secret  
+<a name="MPIN.EXTRACT_FACTOR"></a>
+
+### MPIN.EXTRACT\_FACTOR() ⇒
+Extract factor from TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: token  
+**this**: <code>{MPIN}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN.RESTORE_FACTOR"></a>
+
+### MPIN.RESTORE\_FACTOR() ⇒
+Restore factor to TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: token  
+**this**: <code>{MPIN}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN.GET_SERVER_SECRET"></a>
+
+### MPIN.GET\_SERVER\_SECRET(S, SST) ⇒
+Create a server secret in G2 from a master secret
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | Master secret |
+| SST | Server secret = s.Q where Q is a fixed generator of G2 |
+
+<a name="MPIN.GET_G1_MULTIPLE"></a>
+
+### MPIN.GET\_G1\_MULTIPLE(type, x, G, W) ⇒
+Find a random multiple of a point in G1
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+**Parameter**: rng cryptographically secure random number generator  
+
+| Param | Description |
+| --- | --- |
+| type | determines type of action to be taken |
+| x | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| G | if type=0 a point in G1, else an octet to be mapped to G1 |
+| W | the output =x.G or x.M(G), where M(.) is a mapping |
+
+<a name="MPIN.GET_CLIENT_SECRET"></a>
+
+### MPIN.GET\_CLIENT\_SECRET(S, CID, CST) ⇒
+Create a client secret in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CST | is the full client secret = s.H(ID) |
+
+<a name="MPIN.GET_CLIENT_PERMIT"></a>
+
+### MPIN.GET\_CLIENT\_PERMIT(sha, date, S, CID, CTT) ⇒
+Create a Time Permit in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CTT | is a Time Permit for the given date = s.H(d|H(ID)) |
+
+<a name="MPIN.CLIENT_1"></a>
+
+### MPIN.CLIENT\_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) ⇒
+Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+
+<a name="MPIN.CLIENT_2"></a>
+
+### MPIN.CLIENT\_2(X, Y, SEC) ⇒
+Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| X | an input, a locally generated random number |
+| Y | an input random challenge from the server |
+| SEC | on output = -(x+y).V |
+
+<a name="MPIN.SERVER_1"></a>
+
+### MPIN.SERVER\_1(sha, date, CID, HID, HTID) ⇒
+Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CID | is the input claimed client identity |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+
+<a name="MPIN.SERVER_2"></a>
+
+### MPIN.SERVER\_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) ⇒
+Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is input H(ID), a hash of the client ID |
+| HTID | is input H(ID)+H(d|H(ID)) |
+| Y | is the input server's randomly generated challenge |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| Pa | is the input public key from the client, z.Q or NULL if the client uses regular mpin |
+
+<a name="MPIN.KANGAROO"></a>
+
+### MPIN.KANGAROO(E, F) ⇒
+Use Kangaroos to find PIN error
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 if Kangaroos failed, or the PIN error e  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| E | a member of the group GT |
+| F | a member of the group GT =  E^e |
+
+<a name="MPIN.GET_TIME"></a>
+
+### MPIN.GET\_TIME() ⇒
+Time since epoch
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: time since epoch  
+**this**: <code>{MPIN}</code>  
+<a name="MPIN.GET_Y"></a>
+
+### MPIN.GET\_Y(sha, TimeValue, xCID, Y) ⇒
+Generate Y=H(s,O), where s is epoch time, O is a byte array, and H(.) is a hash function
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| TimeValue | is epoch time in seconds |
+| xCID | input bytearray is an input octet |
+| Y | output value |
+
+<a name="MPIN.CLIENT"></a>
+
+### MPIN.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) ⇒
+Perform client side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| Message | is the message to be signed |
+
+<a name="MPIN.SERVER"></a>
+
+### MPIN.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa) ⇒
+Perform server side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| CID | is the input claimed client identity |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| MESSAGE | is the message to be signed |
+| Pa | is input from the client z.Q or NULL if the key-escrow less scheme is not used |
+
+<a name="MPIN.PRECOMPUTE"></a>
+
+### MPIN.PRECOMPUTE(TOKEN, CID, G1, G2) ⇒
+Precompute values for use by the client side of M-Pin Full
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| CID | is the input client identity |
+| G1 | precomputed output |
+| G2 | precomputed output |
+
+<a name="MPIN.HASH_ALL"></a>
+
+### MPIN.HASH\_ALL(sha, HID, xID, xCID, SEC, Y, R, W) ⇒
+Hash the session transcript
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: H the output is the hash of all of the above that apply  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is the client output = x.H(ID) |
+| xCID | is the client output = x.(H(ID)+H(T|H(ID))) |
+| SEC | is the client part response |
+| Y | is the server challenge |
+| R | is the client part response |
+| W | is the server part response |
+
+<a name="MPIN.CLIENT_KEY"></a>
+
+### MPIN.CLIENT\_KEY(sha, G1, G2, pin, R, X, H, wCID, CK) ⇒
+Calculate Key on Client side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| G1 | precomputed input |
+| G2 | precomputed input |
+| pin | is the input PIN number |
+| R | is an input, a locally generated random number |
+| X | is an input, a locally generated random number |
+| H | is an input, hash of the protocol transcript |
+| wCID | is the input Server-side Diffie-Hellman component |
+| CK | is the output calculated shared key |
+
+<a name="MPIN.SERVER_KEY"></a>
+
+### MPIN.SERVER\_KEY(h, Z, SST, W, H, HID, xID, xCID, SK) ⇒
+Calculate Key on Server side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| h | is the hash type |
+| Z | is the input Client-side Diffie-Hellman component |
+| SST | is the input server secret |
+| W | is an input random number generated by the server |
+| H | is an input, hash of the protocol transcript |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| SK | is the output calculated shared key |
+
+<a name="MPIN.GET_DVS_KEYPAIR"></a>
+
+### MPIN.GET\_DVS\_KEYPAIR(rng, Z, Pa) ⇒
+Generates a random public key for the client z.Q
+
+**Kind**: static method of [<code>MPIN</code>](#MPIN)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| Z | an output internally randomly generated if R!=NULL, otherwise it must be provided as an input |
+| Pa | the output public key for the client |
+
diff --git a/docs/mpin192.md b/docs/mpin192.md
new file mode 100644
index 0000000..952c302
--- /dev/null
+++ b/docs/mpin192.md
@@ -0,0 +1,573 @@
+<a name="MPIN192"></a>
+
+## MPIN192
+**Kind**: global class  
+**this**: <code>{MPIN192}</code>  
+
+* [MPIN192](#MPIN192)
+    * [new MPIN192()](#new_MPIN192_new)
+    * [.today()](#MPIN192.today) ⇒
+    * [.bytestostring(b)](#MPIN192.bytestostring) ⇒
+    * [.stringtobytes(s)](#MPIN192.stringtobytes) ⇒
+    * [.comparebytes(a, b)](#MPIN192.comparebytes) ⇒
+    * [.mpin_hash(c, U)](#MPIN192.mpin_hash) ⇒
+    * [.hashit(sha, n, B)](#MPIN192.hashit) ⇒
+    * [.map(u, cb)](#MPIN192.map) ⇒
+    * [.unmap(u, P)](#MPIN192.unmap) ⇒
+    * [.RECOMBINE_G1(R1, R2, R)](#MPIN192.RECOMBINE_G1) ⇒
+    * [.RECOMBINE_G2(W1, W2, W)](#MPIN192.RECOMBINE_G2) ⇒
+    * [.HASH_ID(sha, ID)](#MPIN192.HASH_ID) ⇒
+    * [.RANDOM_GENERATE(rng, S)](#MPIN192.RANDOM_GENERATE) ⇒
+    * [.EXTRACT_PIN()](#MPIN192.EXTRACT_PIN) ⇒
+    * [.EXTRACT_FACTOR()](#MPIN192.EXTRACT_FACTOR) ⇒
+    * [.RESTORE_FACTOR()](#MPIN192.RESTORE_FACTOR) ⇒
+    * [.GET_SERVER_SECRET(S, SST)](#MPIN192.GET_SERVER_SECRET) ⇒
+    * [.GET_G1_MULTIPLE(type, x, G, W)](#MPIN192.GET_G1_MULTIPLE) ⇒
+    * [.GET_CLIENT_SECRET(S, CID, CST)](#MPIN192.GET_CLIENT_SECRET) ⇒
+    * [.GET_CLIENT_PERMIT(sha, date, S, CID, CTT)](#MPIN192.GET_CLIENT_PERMIT) ⇒
+    * [.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT)](#MPIN192.CLIENT_1) ⇒
+    * [.CLIENT_2(X, Y, SEC)](#MPIN192.CLIENT_2) ⇒
+    * [.SERVER_1(sha, date, CID, HID, HTID)](#MPIN192.SERVER_1) ⇒
+    * [.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa)](#MPIN192.SERVER_2) ⇒
+    * [.KANGAROO(E, F)](#MPIN192.KANGAROO) ⇒
+    * [.GET_TIME()](#MPIN192.GET_TIME) ⇒
+    * [.GET_Y(sha, TimeValue, xCID, Y)](#MPIN192.GET_Y) ⇒
+    * [.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message)](#MPIN192.CLIENT) ⇒
+    * [.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa)](#MPIN192.SERVER) ⇒
+    * [.PRECOMPUTE(TOKEN, CID, G1, G2)](#MPIN192.PRECOMPUTE) ⇒
+    * [.HASH_ALL(sha, HID, xID, xCID, SEC, Y, R, W)](#MPIN192.HASH_ALL) ⇒
+    * [.CLIENT_KEY(sha, G1, G2, pin, R, X, H, wCID, CK)](#MPIN192.CLIENT_KEY) ⇒
+    * [.SERVER_KEY(h, Z, SST, W, H, HID, xID, xCID, SK)](#MPIN192.SERVER_KEY) ⇒
+    * [.GET_DVS_KEYPAIR(rng, Z, Pa)](#MPIN192.GET_DVS_KEYPAIR) ⇒
+
+<a name="new_MPIN192_new"></a>
+
+### new MPIN192()
+Creates an instance of MPIN192
+
+<a name="MPIN192.today"></a>
+
+### MPIN192.today() ⇒
+Get epoch time
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: time in slots since epoch  
+**this**: <code>{MPIN192}</code>  
+<a name="MPIN192.bytestostring"></a>
+
+### MPIN192.bytestostring(b) ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: s string  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array |
+
+<a name="MPIN192.stringtobytes"></a>
+
+### MPIN192.stringtobytes(s) ⇒
+Convert a string to byte array
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: b byte array  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | string |
+
+<a name="MPIN192.comparebytes"></a>
+
+### MPIN192.comparebytes(a, b) ⇒
+Convert byte arrays
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: true if equal  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| a | byte array |
+| b | byte array |
+
+<a name="MPIN192.mpin_hash"></a>
+
+### MPIN192.mpin\_hash(c, U) ⇒
+Hash values
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: R hash value  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+| U | ECP unstancebyte array |
+
+<a name="MPIN192.hashit"></a>
+
+### MPIN192.hashit(sha, n, B) ⇒
+General purpose hash function
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: R hash value  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| n | Integer |
+| B | byte array |
+
+<a name="MPIN192.map"></a>
+
+### MPIN192.map(u, cb) ⇒
+maps a random u to a point on the curve
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: P ECP pointhash value  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| cb | an integer representing the "sign" of y, in fact its least significant bit. |
+
+<a name="MPIN192.unmap"></a>
+
+### MPIN192.unmap(u, P) ⇒
+returns u derived from P. Random value in range 1 to return value should then be added to u
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: r Value that should be added to u to derive P  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| P | ECP pointhash value |
+
+<a name="MPIN192.RECOMBINE_G1"></a>
+
+### MPIN192.RECOMBINE\_G1(R1, R2, R) ⇒
+Add two members from the group G1
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| R1 | Input member of G1 |
+| R2 | Input member of G1 |
+| R | Output member of G1. R=R1+R2 |
+
+<a name="MPIN192.RECOMBINE_G2"></a>
+
+### MPIN192.RECOMBINE\_G2(W1, W2, W) ⇒
+Add two members from the group G2
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| W1 | Input member of G2 |
+| W2 | Input member of G2 |
+| W | Output member of G2. W=W1+W2 |
+
+<a name="MPIN192.HASH_ID"></a>
+
+### MPIN192.HASH\_ID(sha, ID) ⇒
+Hash the identity
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: hash value  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| ID | Identity as byte array |
+
+<a name="MPIN192.RANDOM_GENERATE"></a>
+
+### MPIN192.RANDOM\_GENERATE(rng, S) ⇒
+Create random secret
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| S | Random secret value |
+
+<a name="MPIN192.EXTRACT_PIN"></a>
+
+### MPIN192.EXTRACT\_PIN() ⇒
+Extract a PIN number from a client secret
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: token  
+**this**: <code>{MPIN192}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: pin PIN value  
+**Parameter**: TOKEN Client secret  
+<a name="MPIN192.EXTRACT_FACTOR"></a>
+
+### MPIN192.EXTRACT\_FACTOR() ⇒
+Extract factor from TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: token  
+**this**: <code>{MPIN192}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN192.RESTORE_FACTOR"></a>
+
+### MPIN192.RESTORE\_FACTOR() ⇒
+Restore factor to TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: token  
+**this**: <code>{MPIN192}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN192.GET_SERVER_SECRET"></a>
+
+### MPIN192.GET\_SERVER\_SECRET(S, SST) ⇒
+Create a server secret in G2 from a master secret
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | Master secret |
+| SST | Server secret = s.Q where Q is a fixed generator of G2 |
+
+<a name="MPIN192.GET_G1_MULTIPLE"></a>
+
+### MPIN192.GET\_G1\_MULTIPLE(type, x, G, W) ⇒
+Find a random multiple of a point in G1
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+**Parameter**: rng cryptographically secure random number generator  
+
+| Param | Description |
+| --- | --- |
+| type | determines type of action to be taken |
+| x | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| G | if type=0 a point in G1, else an octet to be mapped to G1 |
+| W | the output =x.G or x.M(G), where M(.) is a mapping |
+
+<a name="MPIN192.GET_CLIENT_SECRET"></a>
+
+### MPIN192.GET\_CLIENT\_SECRET(S, CID, CST) ⇒
+Create a client secret in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CST | is the full client secret = s.H(ID) |
+
+<a name="MPIN192.GET_CLIENT_PERMIT"></a>
+
+### MPIN192.GET\_CLIENT\_PERMIT(sha, date, S, CID, CTT) ⇒
+Create a Time Permit in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CTT | is a Time Permit for the given date = s.H(d|H(ID)) |
+
+<a name="MPIN192.CLIENT_1"></a>
+
+### MPIN192.CLIENT\_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) ⇒
+Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+
+<a name="MPIN192.CLIENT_2"></a>
+
+### MPIN192.CLIENT\_2(X, Y, SEC) ⇒
+Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| X | an input, a locally generated random number |
+| Y | an input random challenge from the server |
+| SEC | on output = -(x+y).V |
+
+<a name="MPIN192.SERVER_1"></a>
+
+### MPIN192.SERVER\_1(sha, date, CID, HID, HTID) ⇒
+Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CID | is the input claimed client identity |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+
+<a name="MPIN192.SERVER_2"></a>
+
+### MPIN192.SERVER\_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) ⇒
+Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is input H(ID), a hash of the client ID |
+| HTID | is input H(ID)+H(d|H(ID)) |
+| Y | is the input server's randomly generated challenge |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| Pa | is the input public key from the client, z.Q or NULL if the client uses regular mpin |
+
+<a name="MPIN192.KANGAROO"></a>
+
+### MPIN192.KANGAROO(E, F) ⇒
+Use Kangaroos to find PIN error
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 if Kangaroos failed, or the PIN error e  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| E | a member of the group GT |
+| F | a member of the group GT =  E^e |
+
+<a name="MPIN192.GET_TIME"></a>
+
+### MPIN192.GET\_TIME() ⇒
+Time since epoch
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: time since epoch  
+**this**: <code>{MPIN192}</code>  
+<a name="MPIN192.GET_Y"></a>
+
+### MPIN192.GET\_Y(sha, TimeValue, xCID, Y) ⇒
+Generate Y=H(s,O), where s is epoch time, O is a byte array, and H(.) is a hash function
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| TimeValue | is epoch time in seconds |
+| xCID | input bytearray is an input octet |
+| Y | output value |
+
+<a name="MPIN192.CLIENT"></a>
+
+### MPIN192.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) ⇒
+Perform client side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| Message | is the message to be signed |
+
+<a name="MPIN192.SERVER"></a>
+
+### MPIN192.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa) ⇒
+Perform server side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| CID | is the input claimed client identity |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| MESSAGE | is the message to be signed |
+| Pa | is input from the client z.Q or NULL if the key-escrow less scheme is not used |
+
+<a name="MPIN192.PRECOMPUTE"></a>
+
+### MPIN192.PRECOMPUTE(TOKEN, CID, G1, G2) ⇒
+Precompute values for use by the client side of M-Pin Full
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| CID | is the input client identity |
+| G1 | precomputed output |
+| G2 | precomputed output |
+
+<a name="MPIN192.HASH_ALL"></a>
+
+### MPIN192.HASH\_ALL(sha, HID, xID, xCID, SEC, Y, R, W) ⇒
+Hash the session transcript
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: H the output is the hash of all of the above that apply  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is the client output = x.H(ID) |
+| xCID | is the client output = x.(H(ID)+H(T|H(ID))) |
+| SEC | is the client part response |
+| Y | is the server challenge |
+| R | is the client part response |
+| W | is the server part response |
+
+<a name="MPIN192.CLIENT_KEY"></a>
+
+### MPIN192.CLIENT\_KEY(sha, G1, G2, pin, R, X, H, wCID, CK) ⇒
+Calculate Key on Client side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| G1 | precomputed input |
+| G2 | precomputed input |
+| pin | is the input PIN number |
+| R | is an input, a locally generated random number |
+| X | is an input, a locally generated random number |
+| H | is an input, hash of the protocol transcript |
+| wCID | is the input Server-side Diffie-Hellman component |
+| CK | is the output calculated shared key |
+
+<a name="MPIN192.SERVER_KEY"></a>
+
+### MPIN192.SERVER\_KEY(h, Z, SST, W, H, HID, xID, xCID, SK) ⇒
+Calculate Key on Server side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| h | is the hash type |
+| Z | is the input Client-side Diffie-Hellman component |
+| SST | is the input server secret |
+| W | is an input random number generated by the server |
+| H | is an input, hash of the protocol transcript |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| SK | is the output calculated shared key |
+
+<a name="MPIN192.GET_DVS_KEYPAIR"></a>
+
+### MPIN192.GET\_DVS\_KEYPAIR(rng, Z, Pa) ⇒
+Generates a random public key for the client z.Q
+
+**Kind**: static method of [<code>MPIN192</code>](#MPIN192)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN192}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| Z | an output internally randomly generated if R!=NULL, otherwise it must be provided as an input |
+| Pa | the output public key for the client |
+
diff --git a/docs/mpin256.md b/docs/mpin256.md
new file mode 100644
index 0000000..e22c5b4
--- /dev/null
+++ b/docs/mpin256.md
@@ -0,0 +1,556 @@
+<a name="MPIN256"></a>
+
+## MPIN256
+**Kind**: global class  
+**this**: <code>{MPIN256}</code>  
+
+* [MPIN256](#MPIN256)
+    * [new MPIN256()](#new_MPIN256_new)
+    * [.today()](#MPIN256.today) ⇒
+    * [.bytestostring(b)](#MPIN256.bytestostring) ⇒
+    * [.stringtobytes(s)](#MPIN256.stringtobytes) ⇒
+    * [.comparebytes(a, b)](#MPIN256.comparebytes) ⇒
+    * [.mpin_hash(c, U)](#MPIN256.mpin_hash) ⇒
+    * [.hashit(sha, n, B)](#MPIN256.hashit) ⇒
+    * [.map(u, cb)](#MPIN256.map) ⇒
+    * [.unmap(u, P)](#MPIN256.unmap) ⇒
+    * [.RECOMBINE_G1(R1, R2, R)](#MPIN256.RECOMBINE_G1) ⇒
+    * [.RECOMBINE_G2(W1, W2, W)](#MPIN256.RECOMBINE_G2) ⇒
+    * [.HASH_ID(sha, ID)](#MPIN256.HASH_ID) ⇒
+    * [.RANDOM_GENERATE(rng, S)](#MPIN256.RANDOM_GENERATE) ⇒
+    * [.EXTRACT_PIN()](#MPIN256.EXTRACT_PIN) ⇒
+    * [.EXTRACT_FACTOR()](#MPIN256.EXTRACT_FACTOR) ⇒
+    * [.RESTORE_FACTOR()](#MPIN256.RESTORE_FACTOR) ⇒
+    * [.GET_SERVER_SECRET(S, SST)](#MPIN256.GET_SERVER_SECRET) ⇒
+    * [.GET_G1_MULTIPLE(type, x, G, W)](#MPIN256.GET_G1_MULTIPLE) ⇒
+    * [.GET_CLIENT_SECRET(S, CID, CST)](#MPIN256.GET_CLIENT_SECRET) ⇒
+    * [.GET_CLIENT_PERMIT(sha, date, S, CID, CTT)](#MPIN256.GET_CLIENT_PERMIT) ⇒
+    * [.CLIENT_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT)](#MPIN256.CLIENT_1) ⇒
+    * [.CLIENT_2(X, Y, SEC)](#MPIN256.CLIENT_2) ⇒
+    * [.SERVER_1(sha, date, CID, HID, HTID)](#MPIN256.SERVER_1) ⇒
+    * [.SERVER_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa)](#MPIN256.SERVER_2) ⇒
+    * [.KANGAROO(E, F)](#MPIN256.KANGAROO) ⇒
+    * [.GET_TIME()](#MPIN256.GET_TIME) ⇒
+    * [.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message)](#MPIN256.CLIENT) ⇒
+    * [.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa)](#MPIN256.SERVER) ⇒
+    * [.PRECOMPUTE(TOKEN, CID, G1, G2)](#MPIN256.PRECOMPUTE) ⇒
+    * [.HASH_ALL(sha, HID, xID, xCID, SEC, Y, R, W)](#MPIN256.HASH_ALL) ⇒
+    * [.CLIENT_KEY(sha, G1, G2, pin, R, X, H, wCID, CK)](#MPIN256.CLIENT_KEY) ⇒
+    * [.SERVER_KEY(h, Z, SST, W, H, HID, xID, xCID, SK)](#MPIN256.SERVER_KEY) ⇒
+    * [.GET_DVS_KEYPAIR(rng, Z, Pa)](#MPIN256.GET_DVS_KEYPAIR) ⇒
+
+<a name="new_MPIN256_new"></a>
+
+### new MPIN256()
+Creates an instance of MPIN256
+
+<a name="MPIN256.today"></a>
+
+### MPIN256.today() ⇒
+Get epoch time for day
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: time in slots since epoch  
+**this**: <code>{MPIN256}</code>  
+<a name="MPIN256.bytestostring"></a>
+
+### MPIN256.bytestostring(b) ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: s string  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array |
+
+<a name="MPIN256.stringtobytes"></a>
+
+### MPIN256.stringtobytes(s) ⇒
+Convert a string to byte array
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: b byte array  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | string |
+
+<a name="MPIN256.comparebytes"></a>
+
+### MPIN256.comparebytes(a, b) ⇒
+Convert byte arrays
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: true if equal  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| a | byte array |
+| b | byte array |
+
+<a name="MPIN256.mpin_hash"></a>
+
+### MPIN256.mpin\_hash(c, U) ⇒
+Hash values
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: R hash value  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| c | FP8 instance |
+| U | ECP unstancebyte array |
+
+<a name="MPIN256.hashit"></a>
+
+### MPIN256.hashit(sha, n, B) ⇒
+General purpose hash function
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: R hash value  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| n | Integer |
+| B | byte array |
+
+<a name="MPIN256.map"></a>
+
+### MPIN256.map(u, cb) ⇒
+maps a random u to a point on the curve
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: P ECP pointhash value  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| cb | an integer representing the "sign" of y, in fact its least significant bit. |
+
+<a name="MPIN256.unmap"></a>
+
+### MPIN256.unmap(u, P) ⇒
+returns u derived from P. Random value in range 1 to return value should then be added to u
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: r Value that should be added to u to derive P  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| u | BIG numberInteger |
+| P | ECP pointhash value |
+
+<a name="MPIN256.RECOMBINE_G1"></a>
+
+### MPIN256.RECOMBINE\_G1(R1, R2, R) ⇒
+Add two members from the group G1
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| R1 | Input member of G1 |
+| R2 | Input member of G1 |
+| R | Output member of G1. R=R1+R2 |
+
+<a name="MPIN256.RECOMBINE_G2"></a>
+
+### MPIN256.RECOMBINE\_G2(W1, W2, W) ⇒
+Add two members from the group G2
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| W1 | Input member of G2 |
+| W2 | Input member of G2 |
+| W | Output member of G2. W=W1+W2 |
+
+<a name="MPIN256.HASH_ID"></a>
+
+### MPIN256.HASH\_ID(sha, ID) ⇒
+Hash the identity
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: hash value  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| ID | Identity as byte array |
+
+<a name="MPIN256.RANDOM_GENERATE"></a>
+
+### MPIN256.RANDOM\_GENERATE(rng, S) ⇒
+Create random secret
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| S | Random secret value |
+
+<a name="MPIN256.EXTRACT_PIN"></a>
+
+### MPIN256.EXTRACT\_PIN() ⇒
+Extract a PIN number from a client secret
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: token  
+**this**: <code>{MPIN256}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: pin PIN value  
+**Parameter**: TOKEN Client secret  
+<a name="MPIN256.EXTRACT_FACTOR"></a>
+
+### MPIN256.EXTRACT\_FACTOR() ⇒
+Extract factor from TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: token  
+**this**: <code>{MPIN256}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN256.RESTORE_FACTOR"></a>
+
+### MPIN256.RESTORE\_FACTOR() ⇒
+Restore factor to TOKEN for identity CID
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: token  
+**this**: <code>{MPIN256}</code>  
+**Parameter**: sha hash type  
+**Parameter**: CID Client identity  
+**Parameter**: factor Value to extract  
+**Parameter**: facbits Number of bits in factor  
+**Parameter**: TOKEN Token value  
+<a name="MPIN256.GET_SERVER_SECRET"></a>
+
+### MPIN256.GET\_SERVER\_SECRET(S, SST) ⇒
+Create a server secret in G2 from a master secret
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | Master secret |
+| SST | Server secret = s.Q where Q is a fixed generator of G2 |
+
+<a name="MPIN256.GET_G1_MULTIPLE"></a>
+
+### MPIN256.GET\_G1\_MULTIPLE(type, x, G, W) ⇒
+Find a random multiple of a point in G1
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+**Parameter**: rng cryptographically secure random number generator  
+
+| Param | Description |
+| --- | --- |
+| type | determines type of action to be taken |
+| x | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| G | if type=0 a point in G1, else an octet to be mapped to G1 |
+| W | the output =x.G or x.M(G), where M(.) is a mapping |
+
+<a name="MPIN256.GET_CLIENT_SECRET"></a>
+
+### MPIN256.GET\_CLIENT\_SECRET(S, CID, CST) ⇒
+Create a client secret in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CST | is the full client secret = s.H(ID) |
+
+<a name="MPIN256.GET_CLIENT_PERMIT"></a>
+
+### MPIN256.GET\_CLIENT\_PERMIT(sha, date, S, CID, CTT) ⇒
+Create a Time Permit in G1 from a master secret and the client ID
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. |
+| S | is an input master secret |
+| CID | is the input client identity |
+| CTT | is a Time Permit for the given date = s.H(d|H(ID)) |
+
+<a name="MPIN256.CLIENT_1"></a>
+
+### MPIN256.CLIENT\_1(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) ⇒
+Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+
+<a name="MPIN256.CLIENT_2"></a>
+
+### MPIN256.CLIENT\_2(X, Y, SEC) ⇒
+Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| X | an input, a locally generated random number |
+| Y | an input random challenge from the server |
+| SEC | on output = -(x+y).V |
+
+<a name="MPIN256.SERVER_1"></a>
+
+### MPIN256.SERVER\_1(sha, date, CID, HID, HTID) ⇒
+Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CID | is the input claimed client identity |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+
+<a name="MPIN256.SERVER_2"></a>
+
+### MPIN256.SERVER\_2(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) ⇒
+Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is input H(ID), a hash of the client ID |
+| HTID | is input H(ID)+H(d|H(ID)) |
+| Y | is the input server's randomly generated challenge |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| Pa | is the input public key from the client, z.Q or NULL if the client uses regular mpin |
+
+<a name="MPIN256.KANGAROO"></a>
+
+### MPIN256.KANGAROO(E, F) ⇒
+Use Kangaroos to find PIN error
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 if Kangaroos failed, or the PIN error e  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| E | a member of the group GT |
+| F | a member of the group GT =  E^e |
+
+<a name="MPIN256.GET_TIME"></a>
+
+### MPIN256.GET\_TIME() ⇒
+Time since epoch
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: time since epoch  
+**this**: <code>{MPIN256}</code>  
+<a name="MPIN256.CLIENT"></a>
+
+### MPIN256.CLIENT(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) ⇒
+Perform client side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| CLIENT_ID | is the input client identity |
+| rng | is a pointer to a cryptographically secure random number generator |
+| X | an output internally randomly generated if R!=NULL, otherwise must be provided as an input |
+| pin | is the input PIN number |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| SEC | is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit |
+| xID | is output = x.H(ID) |
+| xCID | is output = x.(H(ID)+H(d|H(ID))) |
+| PERMIT | is the input time permit |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| Message | is the message to be signed |
+
+<a name="MPIN256.SERVER"></a>
+
+### MPIN256.SERVER(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, MESSAGE, Pa) ⇒
+Perform server side of the one-pass version of the M-Pin protocol
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| date | is input date, in days since the epoch. Set to 0 if Time permits disabled |
+| HID | is output H(ID), a hash of the client ID |
+| HTID | is output H(ID)+H(d|H(ID)) |
+| Y | is output H(t|U) or H(t|UT) if Time Permits enabled |
+| SST | is the input server secret |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| mSEC | is an input from the client |
+| E | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| F | is an output to help the Kangaroos to find the PIN error, or NULL if not required |
+| CID | is the input claimed client identity |
+| TimeValue | is input epoch time in seconds - a timestamp |
+| MESSAGE | is the message to be signed |
+| Pa | is input from the client z.Q or NULL if the key-escrow less scheme is not used |
+
+<a name="MPIN256.PRECOMPUTE"></a>
+
+### MPIN256.PRECOMPUTE(TOKEN, CID, G1, G2) ⇒
+Precompute values for use by the client side of M-Pin Full
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: O for success or else error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| TOKEN | is the input M-Pin token (the client secret with PIN portion removed) |
+| CID | is the input client identity |
+| G1 | precomputed output |
+| G2 | precomputed output |
+
+<a name="MPIN256.HASH_ALL"></a>
+
+### MPIN256.HASH\_ALL(sha, HID, xID, xCID, SEC, Y, R, W) ⇒
+Hash the session transcript
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: H the output is the hash of all of the above that apply  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is the client output = x.H(ID) |
+| xCID | is the client output = x.(H(ID)+H(T|H(ID))) |
+| SEC | is the client part response |
+| Y | is the server challenge |
+| R | is the client part response |
+| W | is the server part response |
+
+<a name="MPIN256.CLIENT_KEY"></a>
+
+### MPIN256.CLIENT\_KEY(sha, G1, G2, pin, R, X, H, wCID, CK) ⇒
+Calculate Key on Client side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| G1 | precomputed input |
+| G2 | precomputed input |
+| pin | is the input PIN number |
+| R | is an input, a locally generated random number |
+| X | is an input, a locally generated random number |
+| H | is an input, hash of the protocol transcript |
+| wCID | is the input Server-side Diffie-Hellman component |
+| CK | is the output calculated shared key |
+
+<a name="MPIN256.SERVER_KEY"></a>
+
+### MPIN256.SERVER\_KEY(h, Z, SST, W, H, HID, xID, xCID, SK) ⇒
+Calculate Key on Server side for M-Pin Full
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| h | is the hash type |
+| Z | is the input Client-side Diffie-Hellman component |
+| SST | is the input server secret |
+| W | is an input random number generated by the server |
+| H | is an input, hash of the protocol transcript |
+| HID | is the hashed input client ID = H(ID) |
+| xID | is input from the client = x.H(ID) |
+| xCID | is input from the client= x.(H(ID)+H(d|H(ID))) |
+| SK | is the output calculated shared key |
+
+<a name="MPIN256.GET_DVS_KEYPAIR"></a>
+
+### MPIN256.GET\_DVS\_KEYPAIR(rng, Z, Pa) ⇒
+Generates a random public key for the client z.Q
+
+**Kind**: static method of [<code>MPIN256</code>](#MPIN256)  
+**Returns**: 0 or an error code  
+**this**: <code>{MPIN256}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | cryptographically secure random number generator |
+| Z | an output internally randomly generated if R!=NULL, otherwise it must be provided as an input |
+| Pa | the output public key for the client |
+
diff --git a/docs/pair.md b/docs/pair.md
new file mode 100644
index 0000000..e430e56
--- /dev/null
+++ b/docs/pair.md
@@ -0,0 +1,174 @@
+<a name="PAIR"></a>
+
+## PAIR
+**Kind**: global class  
+**this**: <code>{PAIR}</code>  
+
+* [PAIR](#PAIR)
+    * [new PAIR()](#new_PAIR_new)
+    * [.line()](#PAIR.line)
+    * [.initmp()](#PAIR.initmp)
+    * [.miller(r, res)](#PAIR.miller)
+    * [.another(r, P1, Q1)](#PAIR.another)
+    * [.ate(P1, Q1)](#PAIR.ate)
+    * [.ate2(P1, Q1, R1, S1)](#PAIR.ate2)
+    * [.fexp(m)](#PAIR.fexp)
+    * [.lbits()](#PAIR.lbits)
+    * [.glv()](#PAIR.glv)
+    * [.gs()](#PAIR.gs)
+    * [.G1mul(P, e)](#PAIR.G1mul) ⇒
+    * [.G2mul(P, e)](#PAIR.G2mul) ⇒
+    * [.GTpow(d, e)](#PAIR.GTpow) ⇒
+
+<a name="new_PAIR_new"></a>
+
+### new PAIR()
+Creates an instance of PAIR
+
+<a name="PAIR.line"></a>
+
+### PAIR.line()
+Line function
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+<a name="PAIR.initmp"></a>
+
+### PAIR.initmp()
+prepare for multi-pairing
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+<a name="PAIR.miller"></a>
+
+### PAIR.miller(r, res)
+basic Miller loop
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | FP12 precomputed array of accumulated line functions |
+| res | FP12 result |
+
+<a name="PAIR.another"></a>
+
+### PAIR.another(r, P1, Q1)
+Precompute line functions for n-pairing
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | array of precomputed FP48 products of line functions |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR.ate"></a>
+
+### PAIR.ate(P1, Q1)
+Calculate Miller loop for Optimal ATE pairing e(P,Q)
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+**Result**: r An element of GT i.e. result of the pairing calculation e(P,Q)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR.ate2"></a>
+
+### PAIR.ate2(P1, Q1, R1, S1)
+Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+**Result**: r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+| R1 | An element of G2 |
+| S1 | An element of G1 |
+
+<a name="PAIR.fexp"></a>
+
+### PAIR.fexp(m)
+Final exponentiation of pairing, converts output of Miller loop to element in GT
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+**Result**: r m^((p^12-1)/r) where p is modulus and r is the group order  
+
+| Param | Description |
+| --- | --- |
+| m | FP12 value |
+
+<a name="PAIR.lbits"></a>
+
+### PAIR.lbits()
+prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+<a name="PAIR.glv"></a>
+
+### PAIR.glv()
+GLV method
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+<a name="PAIR.gs"></a>
+
+### PAIR.gs()
+Galbraith & Scott Method
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**this**: <code>{PAIR}</code>  
+<a name="PAIR.G1mul"></a>
+
+### PAIR.G1mul(P, e) ⇒
+Fast point multiplication of a member of the group G1 by a BIG number
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**Returns**: R Member of G1 R=e.P  
+**this**: <code>{PAIR}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G1 |
+| e | BIG multiplier |
+
+<a name="PAIR.G2mul"></a>
+
+### PAIR.G2mul(P, e) ⇒
+Multiply P by e in group G2
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**Returns**: R Member of G2 R=e.P  
+**this**: <code>{PAIR}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G2 |
+| e | BIG multiplier |
+
+<a name="PAIR.GTpow"></a>
+
+### PAIR.GTpow(d, e) ⇒
+Fast raising of a member of GT to a BIG power
+
+**Kind**: static method of [<code>PAIR</code>](#PAIR)  
+**Returns**: r d^e  
+**this**: <code>{PAIR}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | Member of GT |
+| e | BIG exponent |
+
diff --git a/docs/pair192.md b/docs/pair192.md
new file mode 100644
index 0000000..7b74e7f
--- /dev/null
+++ b/docs/pair192.md
@@ -0,0 +1,174 @@
+<a name="PAIR192"></a>
+
+## PAIR192
+**Kind**: global class  
+**this**: <code>{PAIR192}</code>  
+
+* [PAIR192](#PAIR192)
+    * [new PAIR192()](#new_PAIR192_new)
+    * [.line()](#PAIR192.line)
+    * [.initmp()](#PAIR192.initmp)
+    * [.miller(r, res)](#PAIR192.miller)
+    * [.another(r, P1, Q1)](#PAIR192.another)
+    * [.ate(P1, Q1)](#PAIR192.ate)
+    * [.ate2(P1, Q1, R1, S1)](#PAIR192.ate2)
+    * [.fexp(m)](#PAIR192.fexp)
+    * [.lbits()](#PAIR192.lbits)
+    * [.glv()](#PAIR192.glv)
+    * [.gs()](#PAIR192.gs)
+    * [.G1mul(P, e)](#PAIR192.G1mul) ⇒
+    * [.G2mul(P, e)](#PAIR192.G2mul) ⇒
+    * [.GTpow(d, e)](#PAIR192.GTpow) ⇒
+
+<a name="new_PAIR192_new"></a>
+
+### new PAIR192()
+Creates an instance of PAIR192
+
+<a name="PAIR192.line"></a>
+
+### PAIR192.line()
+Line function
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+<a name="PAIR192.initmp"></a>
+
+### PAIR192.initmp()
+prepare for multi-pairing
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+<a name="PAIR192.miller"></a>
+
+### PAIR192.miller(r, res)
+basic Miller loop
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | FP24 precomputed array of accumulated line functions |
+| res | FP24 result |
+
+<a name="PAIR192.another"></a>
+
+### PAIR192.another(r, P1, Q1)
+Precompute line functions for n-pairing
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | array of precomputed FP24 products of line functions |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR192.ate"></a>
+
+### PAIR192.ate(P1, Q1)
+Calculate Miller loop for Optimal ATE pairing e(P,Q)
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+**Result**: r An element of GT i.e. result of the pairing calculation e(P,Q)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR192.ate2"></a>
+
+### PAIR192.ate2(P1, Q1, R1, S1)
+Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+**Result**: r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+| R1 | An element of G2 |
+| S1 | An element of G1 |
+
+<a name="PAIR192.fexp"></a>
+
+### PAIR192.fexp(m)
+Final exponentiation of pairing, converts output of Miller loop to element in GT
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+**Result**: r m^((p^12-1)/r) where p is modulus and r is the group order  
+
+| Param | Description |
+| --- | --- |
+| m | FP24 value |
+
+<a name="PAIR192.lbits"></a>
+
+### PAIR192.lbits()
+prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+<a name="PAIR192.glv"></a>
+
+### PAIR192.glv()
+GLV method
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+<a name="PAIR192.gs"></a>
+
+### PAIR192.gs()
+Galbraith & Scott Method
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**this**: <code>{PAIR192}</code>  
+<a name="PAIR192.G1mul"></a>
+
+### PAIR192.G1mul(P, e) ⇒
+Fast point multiplication of a member of the group G1 by a BIG number
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**Returns**: R Member of G1 R=e.P  
+**this**: <code>{PAIR192}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G1 |
+| e | BIG multiplier |
+
+<a name="PAIR192.G2mul"></a>
+
+### PAIR192.G2mul(P, e) ⇒
+Multiply P by e in group G2
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**Returns**: R Member of G2 R=e.P  
+**this**: <code>{PAIR192}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G2 |
+| e | BIG multiplier |
+
+<a name="PAIR192.GTpow"></a>
+
+### PAIR192.GTpow(d, e) ⇒
+Fast raising of a member of GT to a BIG power
+
+**Kind**: static method of [<code>PAIR192</code>](#PAIR192)  
+**Returns**: r d^e  
+**this**: <code>{PAIR192}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | Member of GT |
+| e | BIG exponent |
+
diff --git a/docs/pair256.md b/docs/pair256.md
new file mode 100644
index 0000000..9841607
--- /dev/null
+++ b/docs/pair256.md
@@ -0,0 +1,174 @@
+<a name="PAIR256"></a>
+
+## PAIR256
+**Kind**: global class  
+**this**: <code>{PAIR256}</code>  
+
+* [PAIR256](#PAIR256)
+    * [new PAIR256()](#new_PAIR256_new)
+    * [.line()](#PAIR256.line)
+    * [.initmp()](#PAIR256.initmp)
+    * [.miller(r, res)](#PAIR256.miller)
+    * [.another(r, P1, Q1)](#PAIR256.another)
+    * [.ate(P1, Q1)](#PAIR256.ate)
+    * [.ate2(P1, Q1, R1, S1)](#PAIR256.ate2)
+    * [.fexp(m)](#PAIR256.fexp)
+    * [.lbits()](#PAIR256.lbits)
+    * [.glv()](#PAIR256.glv)
+    * [.gs()](#PAIR256.gs)
+    * [.G1mul(P, e)](#PAIR256.G1mul) ⇒
+    * [.G2mul(P, e)](#PAIR256.G2mul) ⇒
+    * [.GTpow(d, e)](#PAIR256.GTpow) ⇒
+
+<a name="new_PAIR256_new"></a>
+
+### new PAIR256()
+Creates an instance of PAIR256
+
+<a name="PAIR256.line"></a>
+
+### PAIR256.line()
+Line function
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+<a name="PAIR256.initmp"></a>
+
+### PAIR256.initmp()
+prepare for multi-pairing
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+<a name="PAIR256.miller"></a>
+
+### PAIR256.miller(r, res)
+basic Miller loop
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | FP48 precomputed array of accumulated line functions |
+| res | FP48 result |
+
+<a name="PAIR256.another"></a>
+
+### PAIR256.another(r, P1, Q1)
+Precompute line functions for n-pairing
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+
+| Param | Description |
+| --- | --- |
+| r | array of precomputed FP48 products of line functions |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR256.ate"></a>
+
+### PAIR256.ate(P1, Q1)
+Calculate Miller loop for Optimal ATE pairing e(P,Q)
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+**Result**: r An element of GT i.e. result of the pairing calculation e(P,Q)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+
+<a name="PAIR256.ate2"></a>
+
+### PAIR256.ate2(P1, Q1, R1, S1)
+Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+**Result**: r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)  
+
+| Param | Description |
+| --- | --- |
+| P1 | An element of G2 |
+| Q1 | An element of G1 |
+| R1 | An element of G2 |
+| S1 | An element of G1 |
+
+<a name="PAIR256.fexp"></a>
+
+### PAIR256.fexp(m)
+Final exponentiation of pairing, converts output of Miller loop to element in GT
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+**Result**: r m^((p^12-1)/r) where p is modulus and r is the group order  
+
+| Param | Description |
+| --- | --- |
+| m | FP48 value |
+
+<a name="PAIR256.lbits"></a>
+
+### PAIR256.lbits()
+prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+<a name="PAIR256.glv"></a>
+
+### PAIR256.glv()
+GLV method
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+<a name="PAIR256.gs"></a>
+
+### PAIR256.gs()
+Galbraith & Scott Method
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**this**: <code>{PAIR256}</code>  
+<a name="PAIR256.G1mul"></a>
+
+### PAIR256.G1mul(P, e) ⇒
+Fast point multiplication of a member of the group G1 by a BIG number
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**Returns**: R Member of G1 R=e.P  
+**this**: <code>{PAIR256}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G1 |
+| e | BIG multiplier |
+
+<a name="PAIR256.G2mul"></a>
+
+### PAIR256.G2mul(P, e) ⇒
+Multiply P by e in group G2
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**Returns**: R Member of G2 R=e.P  
+**this**: <code>{PAIR256}</code>  
+
+| Param | Description |
+| --- | --- |
+| P | Member of G2 |
+| e | BIG multiplier |
+
+<a name="PAIR256.GTpow"></a>
+
+### PAIR256.GTpow(d, e) ⇒
+Fast raising of a member of GT to a BIG power
+
+**Kind**: static method of [<code>PAIR256</code>](#PAIR256)  
+**Returns**: r d^e  
+**this**: <code>{PAIR256}</code>  
+
+| Param | Description |
+| --- | --- |
+| d | Member of GT |
+| e | BIG exponent |
+
diff --git a/docs/rand.md b/docs/rand.md
new file mode 100644
index 0000000..53527cd
--- /dev/null
+++ b/docs/rand.md
@@ -0,0 +1,62 @@
+<a name="RAND"></a>
+
+## RAND
+**Kind**: global class  
+**this**: <code>{RAND}</code>  
+
+* [RAND](#RAND)
+    * [new RAND()](#new_RAND_new)
+    * _instance_
+        * [.clean()](#RAND+clean)
+        * [.sbrand()](#RAND+sbrand)
+        * [.seed(rawlen, raw)](#RAND+seed)
+        * [.getByte()](#RAND+getByte)
+    * _static_
+        * [.pack()](#RAND.pack)
+
+<a name="new_RAND_new"></a>
+
+### new RAND()
+Creates an instance of RAND
+
+<a name="RAND+clean"></a>
+
+### ranD.clean()
+Delete all internal state of a random number generator
+
+**Kind**: instance method of [<code>RAND</code>](#RAND)  
+**this**: <code>{RAND}</code>  
+<a name="RAND+sbrand"></a>
+
+### ranD.sbrand()
+Marsaglia & Zaman random number generator
+
+**Kind**: instance method of [<code>RAND</code>](#RAND)  
+**this**: <code>{RAND}</code>  
+<a name="RAND+seed"></a>
+
+### ranD.seed(rawlen, raw)
+Initialize RNG with some real entropy from some external source
+
+**Kind**: instance method of [<code>RAND</code>](#RAND)  
+**this**: <code>{RAND}</code>  
+
+| Param | Description |
+| --- | --- |
+| rawlen | the number of seed bytes provided |
+| raw | an array of seed bytes |
+
+<a name="RAND+getByte"></a>
+
+### ranD.getByte()
+Get random byte
+
+**Kind**: instance method of [<code>RAND</code>](#RAND)  
+**this**: <code>{RAND}</code>  
+<a name="RAND.pack"></a>
+
+### RAND.pack()
+Pack 4 bytes into a 32-bit Word
+
+**Kind**: static method of [<code>RAND</code>](#RAND)  
+**this**: <code>{RAND}</code>  
diff --git a/docs/rsa.md b/docs/rsa.md
new file mode 100644
index 0000000..f45d5fb
--- /dev/null
+++ b/docs/rsa.md
@@ -0,0 +1,222 @@
+## Classes
+
+<dl>
+<dt><a href="#RSA">RSA</a></dt>
+<dd></dd>
+<dt><a href="#rsa_private_key">rsa_private_key</a></dt>
+<dd></dd>
+<dt><a href="#rsa_public_key">rsa_public_key</a></dt>
+<dd></dd>
+</dl>
+
+<a name="RSA"></a>
+
+## RSA
+**Kind**: global class  
+**this**: <code>{RSA}</code>  
+
+* [RSA](#RSA)
+    * [new RSA()](#new_RSA_new)
+    * [.bytestohex(b)](#RSA.bytestohex) ⇒
+    * [.bytestostring(b)](#RSA.bytestostring) ⇒
+    * [.stringtobytes(s)](#RSA.stringtobytes) ⇒
+    * [.hashit(sha, A, n)](#RSA.hashit) ⇒
+    * [.KEY_PAIR(rng, e, PRIV, PUB)](#RSA.KEY_PAIR)
+    * [.PKCS15(rng, e, PRIV, PUB)](#RSA.PKCS15) ⇒
+    * [.OAEP_ENCODE(sha, m, rng, P)](#RSA.OAEP_ENCODE) ⇒
+    * [.OAEP_DECODE(sha, P, f)](#RSA.OAEP_DECODE) ⇒
+    * [.PRIVATE_KEY_KILL(PRIV)](#RSA.PRIVATE_KEY_KILL)
+    * [.ENCRYPT(PUB, F, G)](#RSA.ENCRYPT)
+    * [.DECRYPT(PRIV, G, F)](#RSA.DECRYPT)
+
+<a name="new_RSA_new"></a>
+
+### new RSA()
+Creates an instance of RSA
+
+<a name="RSA.bytestohex"></a>
+
+### RSA.bytestohex(b) ⇒
+Convert byte array to hex string
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: s hex string  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array |
+
+<a name="RSA.bytestostring"></a>
+
+### RSA.bytestostring(b) ⇒
+Convert byte array to string
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: s string  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| b | byte array |
+
+<a name="RSA.stringtobytes"></a>
+
+### RSA.stringtobytes(s) ⇒
+Convert a string to byte array
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: b byte array  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| s | string |
+
+<a name="RSA.hashit"></a>
+
+### RSA.hashit(sha, A, n) ⇒
+General purpose hash function
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: R hash value  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| A | byte array |
+| n | Integer |
+
+<a name="RSA.KEY_PAIR"></a>
+
+### RSA.KEY\_PAIR(rng, e, PRIV, PUB)
+RSA Key Pair Generator
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | is a pointer to a cryptographically secure random number generator |
+| e | the encryption exponent |
+| PRIV | the output RSA private key |
+| PUB | the output RSA public key |
+
+<a name="RSA.PKCS15"></a>
+
+### RSA.PKCS15(rng, e, PRIV, PUB) ⇒
+PKCS V1.5 padding of a message prior to RSA signature
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: true or false  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| rng | is a pointer to a cryptographically secure random number generator |
+| e | the encryption exponent |
+| PRIV | the output RSA private key |
+| PUB | the output RSA public key |
+
+<a name="RSA.OAEP_ENCODE"></a>
+
+### RSA.OAEP\_ENCODE(sha, m, rng, P) ⇒
+OAEP padding of a message prior to RSA encryption
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: f is the output encoding, ready for RSA encryption  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| m | is the input message |
+| rng | is a pointer to a cryptographically secure random number generator |
+| P | are input encoding parameter string (could be NULL) |
+
+<a name="RSA.OAEP_DECODE"></a>
+
+### RSA.OAEP\_DECODE(sha, P, f) ⇒
+OAEP unpadding of a message after RSA decryption
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**Returns**: r is the unpadded message  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| sha | is the hash type |
+| P | are input encoding parameter string (could be NULL) |
+| f | is the padded message |
+
+<a name="RSA.PRIVATE_KEY_KILL"></a>
+
+### RSA.PRIVATE\_KEY\_KILL(PRIV)
+Destroy an RSA private Key
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| PRIV | the input RSA private key. Destroyed on output. |
+
+<a name="RSA.ENCRYPT"></a>
+
+### RSA.ENCRYPT(PUB, F, G)
+RSA encryption of suitably padded plaintext
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| PUB | the input RSA public key |
+| F | is input padded message |
+| G | is the output ciphertext |
+
+<a name="RSA.DECRYPT"></a>
+
+### RSA.DECRYPT(PRIV, G, F)
+RSA decryption of ciphertext
+
+**Kind**: static method of [<code>RSA</code>](#RSA)  
+**this**: <code>{RSA}</code>  
+
+| Param | Description |
+| --- | --- |
+| PRIV | the input RSA private key |
+| G | is the input ciphertext |
+| F | is output plaintext (requires unpadding) |
+
+<a name="rsa_private_key"></a>
+
+## rsa\_private\_key
+**Kind**: global class  
+**this**: <code>{rsa\_private\_key}</code>  
+<a name="new_rsa_private_key_new"></a>
+
+### new rsa\_private\_key(n)
+Creates an instance of rsa_private_key
+
+
+| Param | Description |
+| --- | --- |
+| n | FF length |
+
+<a name="rsa_public_key"></a>
+
+## rsa\_public\_key
+**Kind**: global class  
+**this**: <code>{rsa\_private\_key}</code>  
+<a name="new_rsa_public_key_new"></a>
+
+### new rsa\_public\_key(m)
+Creates an instance of rsa_public_key
+
+
+| Param | Description |
+| --- | --- |
+| m | FF length |
+
diff --git a/docs/sha3.md b/docs/sha3.md
new file mode 100644
index 0000000..9c54ff2
--- /dev/null
+++ b/docs/sha3.md
@@ -0,0 +1,68 @@
+<a name="SHA3"></a>
+
+## SHA3
+**Kind**: global class  
+**this**: <code>{SHA3}</code>  
+
+* [SHA3](#SHA3)
+    * [new SHA3(olen)](#new_SHA3_new)
+    * [.init(olen)](#SHA3+init)
+    * [.process()](#SHA3+process)
+    * [.hash(buff)](#SHA3+hash)
+    * [.shake(buff, olen)](#SHA3+shake)
+
+<a name="new_SHA3_new"></a>
+
+### new SHA3(olen)
+Creates an instance of SHA3
+
+
+| Param | Description |
+| --- | --- |
+| olen | output length |
+
+<a name="SHA3+init"></a>
+
+### shA3.init(olen)
+Initialise an instance of SHA3
+
+**Kind**: instance method of [<code>SHA3</code>](#SHA3)  
+**this**: <code>{SHA3}</code>  
+
+| Param | Description |
+| --- | --- |
+| olen | output length |
+
+<a name="SHA3+process"></a>
+
+### shA3.process()
+Process a byte for SHA3
+
+**Kind**: instance method of [<code>SHA3</code>](#SHA3)  
+**this**: <code>{SHA3}</code>  
+**Byt**: byte of date to be processed  
+<a name="SHA3+hash"></a>
+
+### shA3.hash(buff)
+Create fixed length hash output of SHA3
+
+**Kind**: instance method of [<code>SHA3</code>](#SHA3)  
+**this**: <code>{SHA3}</code>  
+
+| Param | Description |
+| --- | --- |
+| buff | byte array to store hash |
+
+<a name="SHA3+shake"></a>
+
+### shA3.shake(buff, olen)
+Create variable length hash output of SHA3
+
+**Kind**: instance method of [<code>SHA3</code>](#SHA3)  
+**this**: <code>{SHA3}</code>  
+
+| Param | Description |
+| --- | --- |
+| buff | byte array to store hash |
+| olen | length of the hash |
+
diff --git a/docs/uint64.md b/docs/uint64.md
new file mode 100644
index 0000000..7fed1f8
--- /dev/null
+++ b/docs/uint64.md
@@ -0,0 +1,49 @@
+<a name="UInt64"></a>
+
+## UInt64
+**Kind**: global class  
+**this**: <code>{UInt64}</code>  
+
+* [UInt64](#UInt64)
+    * [new UInt64(top, bot)](#new_UInt64_new)
+    * [.add(y)](#UInt64+add)
+    * [.copy()](#UInt64+copy)
+    * [.shlb()](#UInt64+shlb)
+
+<a name="new_UInt64_new"></a>
+
+### new UInt64(top, bot)
+Creates an instance of UInt64. Rudimentary unsigned 64-bit type for SHA384 and SHA512
+
+
+| Param | Description |
+| --- | --- |
+| top | Top 32 bits |
+| bot | Bottom 32 bits |
+
+<a name="UInt64+add"></a>
+
+### uInt64.add(y)
+Add value
+
+**Kind**: instance method of [<code>UInt64</code>](#UInt64)  
+**this**: <code>{UInt64}</code>  
+
+| Param | Description |
+| --- | --- |
+| y | UInt64 value |
+
+<a name="UInt64+copy"></a>
+
+### uInt64.copy()
+Copy value
+
+**Kind**: instance method of [<code>UInt64</code>](#UInt64)  
+**this**: <code>{UInt64}</code>  
+<a name="UInt64+shlb"></a>
+
+### uInt64.shlb()
+Shift left
+
+**Kind**: instance method of [<code>UInt64</code>](#UInt64)  
+**this**: <code>{UInt64}</code>  
diff --git a/examples/browser/example_BLS.html b/examples/browser/example_BLS.html
index ab8cbf4..7fed187 100644
--- a/examples/browser/example_BLS.html
+++ b/examples/browser/example_BLS.html
@@ -1,3 +1,22 @@
+<!--
+    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.
+-->
+
 <!DOCTYPE HTML>
 <html>
 <head>
diff --git a/examples/browser/example_all.html b/examples/browser/example_all.html
index 24fb9ab..5dc7a1a 100644
--- a/examples/browser/example_all.html
+++ b/examples/browser/example_all.html
@@ -1,3 +1,22 @@
+<!--
+    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.
+-->
+
 <!DOCTYPE HTML>
 <html>
 <head>
diff --git a/examples/node/example_AES_ENCRYPTION.js b/examples/node/example_AES_ENCRYPTION.js
index c0d2525..16fb8af 100644
--- a/examples/node/example_AES_ENCRYPTION.js
+++ b/examples/node/example_AES_ENCRYPTION.js
@@ -1,23 +1,23 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-/* Test HASH function - test driver and function exerciser for SHA256, SHA384, SHA512 API Functions */
+// Test AES 
 
 var CTX = require("../../index");
 
diff --git a/examples/node/example_BLS_BLS381.js b/examples/node/example_BLS_BLS381.js
index fc28aa2..f7f2c77 100644
--- a/examples/node/example_BLS_BLS381.js
+++ b/examples/node/example_BLS_BLS381.js
@@ -1,3 +1,22 @@
+/*
+    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.
+*/
+
 /* Test BLS - test driver and function exerciser for BLS API Functions */
 
 var CTX = require("../../index");
diff --git a/examples/node/example_DVS_BLS381.js b/examples/node/example_DVS_BLS381.js
index 416892c..b01a1fe 100644
--- a/examples/node/example_DVS_BLS381.js
+++ b/examples/node/example_DVS_BLS381.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test DVS - test driver and function exerciser for Designated Verifier Signature API Functions */
diff --git a/examples/node/example_ECC_BLS381_NIST521.js b/examples/node/example_ECC_BLS381_NIST521.js
index 9849b78..e1aa886 100644
--- a/examples/node/example_ECC_BLS381_NIST521.js
+++ b/examples/node/example_ECC_BLS381_NIST521.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test ECC - test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
 
 var CTX = require("../../index");
diff --git a/examples/node/example_ECC_NIST256.js b/examples/node/example_ECC_NIST256.js
index f661be6..27bd5e3 100644
--- a/examples/node/example_ECC_NIST256.js
+++ b/examples/node/example_ECC_NIST256.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test ECC - test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
 
 var CTX = require("../../index");
diff --git a/examples/node/example_HASH.js b/examples/node/example_HASH.js
index 6ff0d0d..18b23fa 100644
--- a/examples/node/example_HASH.js
+++ b/examples/node/example_HASH.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Example Hash functions */
diff --git a/examples/node/example_MPIN_BLS381.js b/examples/node/example_MPIN_BLS381.js
index 11e2b78..a8e5c24 100644
--- a/examples/node/example_MPIN_BLS381.js
+++ b/examples/node/example_MPIN_BLS381.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test MPIN - test driver and function exerciser for MPIN API Functions */
diff --git a/examples/node/example_MPIN_FULL_BLS381.js b/examples/node/example_MPIN_FULL_BLS381.js
index 0e9f9a3..a9e7ba1 100644
--- a/examples/node/example_MPIN_FULL_BLS381.js
+++ b/examples/node/example_MPIN_FULL_BLS381.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test MPIN - test driver and function exerciser for MPIN API Functions */
diff --git a/examples/node/example_MPIN_ONE_PASS_BLS381.js b/examples/node/example_MPIN_ONE_PASS_BLS381.js
index 9de9ba6..4d3b829 100644
--- a/examples/node/example_MPIN_ONE_PASS_BLS381.js
+++ b/examples/node/example_MPIN_ONE_PASS_BLS381.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test MPIN - test driver and function exerciser for MPIN API Functions */
diff --git a/examples/node/example_RSA2048_ECDSA_NIST256.js b/examples/node/example_RSA2048_ECDSA_NIST256.js
index 7b6aa86..78dab3f 100644
--- a/examples/node/example_RSA2048_ECDSA_NIST256.js
+++ b/examples/node/example_RSA2048_ECDSA_NIST256.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test RSA - test driver and function exerciser for RSA_2048 and ECDSA with NIST256 */
diff --git a/examples/node/example_RSA2048_GENKEY.js b/examples/node/example_RSA2048_GENKEY.js
index d462571..f849ffc 100644
--- a/examples/node/example_RSA2048_GENKEY.js
+++ b/examples/node/example_RSA2048_GENKEY.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test RSA - test driver and function exerciser for RSA_2048 API Functions */
diff --git a/index.js b/index.js
index 8a4b508..f4b405e 100644
--- a/index.js
+++ b/index.js
@@ -1 +1,20 @@
+/**
+    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.
+*/
+
 module.exports = require("./src/ctx");
diff --git a/src/aes.js b/src/aes.js
index 73f8425..298fe2b 100644
--- a/src/aes.js
+++ b/src/aes.js
@@ -20,6 +20,12 @@
 var AES = function() {
     "use strict";
 
+    /**
+     * Creates an instance of AES.
+     *
+     * @constructor
+     * @this {AES}
+     */
     var AES = function() {
         this.Nk = 0;
         this.Nr = 0;
@@ -47,7 +53,14 @@
     AES.CTR16 = 45;
 
     AES.prototype = {
-        /* reset cipher */
+
+	/**
+         * Reset AES mode or IV
+         *
+         * @this {AES}
+         * @param m  The new active mode of operation (ECB, CBC, OFB, CFB etc)
+         * @param iv The new Initialisation Vector
+         */
         reset: function(m, iv) { /* reset mode, or reset iv */
             var i;
 
@@ -64,6 +77,12 @@
             }
         },
 
+	/**
+         * Reset Extract chaining vector
+         *
+         * @this {AES}
+         * @return f the extracted chaining vector
+         */
         getreg: function() {
             var ir = [],
                 i;
@@ -87,7 +106,15 @@
             }
         },
 
-        /* Initialise cipher */
+	/**
+         * Initialise an instance of AES and its mode of operation
+         *
+         * @this {AES}
+         * @param m is the active mode of operation (ECB, CBC, OFB, CFB etc)
+         * @param n is the key length in bytes, 16, 24 or 32
+         * @param key the AES key as an array of 16 bytes
+         * @param iv the Initialisation Vector
+         */
         init: function(m, nk, key, iv) { /* Key=16 bytes */
             /* Key Scheduler. Create expanded encryption key */
             var CipherKey = [],
@@ -160,7 +187,12 @@
             }
         },
 
-        /* Encrypt a single block */
+	/**
+         * Encrypt a single 16 byte block in ECB mode
+         *
+         * @this {AES}
+         * @param {string} buff is an array of 16 plaintext bytes, on exit becomes ciphertext
+         */
         ecb_encrypt: function(buff) {
             var b = [],
                 p = [],
@@ -234,7 +266,12 @@
             }
         },
 
-        /* Decrypt a single block */
+	/**
+         * Decrypt a single 16 byte block in ECB mode
+         *
+         * @this {AES}
+         * @param buff is an array of 16 cipherext bytes, on exit becomes plaintext
+         */	
         ecb_decrypt: function(buff) {
             var b = [],
                 p = [],
@@ -307,7 +344,12 @@
 
         },
 
-        /* Encrypt using selected mode of operation */
+	/**
+         * Encrypt using selected mode of operation 
+         *
+         * @this {AES}
+         * @param {string} buff is an array of 16 plaintext bytes, on exit becomes ciphertext
+         */
         encrypt: function(buff) {
             var st = [],
                 bytes, fell_off, j;
@@ -384,7 +426,12 @@
             }
         },
 
-        /* Decrypt using selected mode of operation */
+	/**
+         * Decrypt using selected mode of operation 
+         *
+         * @this {AES}
+         * @param {string} buff is an array of 16 cipherext bytes, on exit becomes plaintext
+         */	
         decrypt: function(buff) {
             var st = [],
                 bytes,fell_off, j;
@@ -461,7 +508,11 @@
             }
         },
 
-        /* Clean up and delete left-overs */
+	/**
+         * Clean up and delete left-overs 
+         *
+         * @this {AES}
+         */		
         end: function() { // clean up
             var i;
 
diff --git a/src/big.js b/src/big.js
index f680841..07226ed 100644
--- a/src/big.js
+++ b/src/big.js
@@ -24,7 +24,12 @@
 BIG = function(ctx) {
     "use strict";
 
-    /* General purpose Constructor */
+    /**
+     * General purpose Constructor 
+     *
+     * @constructor
+     * @this {BIG}
+     */    
     var BIG = function(x) {
         this.w = new Array(BIG.NLEN);
 
@@ -54,7 +59,13 @@
     BIG.MODINV = (Math.pow(2, -BIG.BASEBITS));
 
     BIG.prototype = {
-        /* set to zero */
+
+	/**
+         * set to zero
+         *
+         * @this {BIG}
+         * @return BIG number
+         */
         zero: function() {
             var i;
 
@@ -65,7 +76,12 @@
             return this;
         },
 
-        /* set to one */
+	/**
+         * set to one
+         *
+         * @this {BIG}
+         * @return BIG number
+         */	
         one: function() {
             var i;
 
@@ -85,7 +101,12 @@
             this.w[i] = x;
         },
 
-        /* test for zero */
+	/**
+         * test for zero 
+         *
+         * @this {BIG}
+         * @return True if zero
+         */		
         iszilch: function() {
             var i;
 
@@ -98,7 +119,12 @@
             return true;
         },
 
-        /* test for unity */
+	/**
+         * test for unity 
+         *
+         * @this {BIG}
+         * @return True if one
+         */		
         isunity: function() {
             var i;
 
@@ -115,7 +141,13 @@
             return true;
         },
 
-        /* Conditional swap of two BIGs depending on d using XOR - no branches */
+	/**
+         * Conditional swap of two BIGs depending on d using XOR - no branches 
+         *
+         * @this {BIG}
+         * @parameter b BIG number 
+         * @parameter d BIG number 
+         */		
         cswap: function(b, d) {
             var c = d,
                 t, i;
@@ -129,7 +161,13 @@
             }
         },
 
-        /* Conditional move of BIG depending on d using XOR - no branches */
+	/**
+         * Conditional move of BIG depending on d using XOR - no branches 
+         *
+         * @this {BIG}
+         * @parameter b BIG number 
+         * @parameter d BIG number 
+         */			
         cmove: function(b, d) {
             var c = d,
                 i;
@@ -141,7 +179,13 @@
             }
         },
 
-        /* copy from another BIG */
+	/**
+         * Copy from another BIG 
+         *
+         * @this {BIG}
+         * @parameter y BIG number 
+         * @return The BIG object
+         */				
         copy: function(y) {
             var i;
 
@@ -152,7 +196,13 @@
             return this;
         },
 
-        /* copy from bottom half of ctx.DBIG */
+	/**
+         * copy from bottom half of ctx.DBIG 
+         *
+         * @this {BIG}
+         * @parameter y BIG number 
+         * @return The new BIG object
+         */				
         hcopy: function(y) {
             var i;
 
@@ -163,7 +213,13 @@
             return this;
         },
 
-        /* copy from ROM */
+	/**
+         *  copy from ROM 
+         *
+         * @this {BIG}
+         * @parameter y BIG number in ROM
+         * @return The BIG object
+         */				
         rcopy: function(y) {
             var i;
 
@@ -182,7 +238,12 @@
             this.w[BIG.NLEN - 1] |= x;
         },
 
-        /* normalise BIG - force all digits < 2^BASEBITS */
+	/**
+         *  normalise BIG - force all digits < 2^BASEBITS 
+         *
+         * @this {BIG}
+         * @return BIG number
+         */					
         norm: function() {
             var carry = 0,
                 d, i;
@@ -198,7 +259,13 @@
             return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS));
         },
 
-        /* quick shift right by less than a word */
+	/**
+         * Quick Fast shifts a BIG right by a small number of bits - input must be normalised, output will be normalised
+         *
+         * @this {BIG}
+         * @parameter k Number of bits to shift
+         * @return r The shifted out part
+         */					
         fshr: function(k) {
             var r, i;
 
@@ -213,7 +280,13 @@
             return r;
         },
 
-        /* General shift right by k bits */
+	/**
+         * General shift right by k bits 
+         *
+         * @this {BIG}
+         * @parameter k Number of bits to shift
+         * @return BIG number
+         */						
         shr: function(k) {
             var n = k % BIG.BASEBITS,
                 m = Math.floor(k / BIG.BASEBITS),
@@ -232,7 +305,13 @@
             return this;
         },
 
-        /* quick shift left by less than a word */
+	/**
+         * Fast shifts a BIG left by a small number of bits - input must be normalised, output will be normalised
+         *
+         * @this {BIG}
+         * @parameter k Number of bits to shift
+         * @return r The shifted out part
+         */							
         fshl: function(k) {
             var i;
 
@@ -247,7 +326,13 @@
             return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS)); /* return excess - only used in FF.java */
         },
 
-        /* General shift left by k bits */
+	/**
+         * General shift left by k bits
+         *
+         * @this {BIG}
+         * @parameter k Number of bits to shift
+         * @return BIG number 
+         */							
         shl: function(k) {
             var n = k % BIG.BASEBITS,
                 m = Math.floor(k / BIG.BASEBITS),
@@ -272,7 +357,12 @@
             return this;
         },
 
-        /* return length in bits */
+	/**
+         * length in bits 
+         *
+         * @this {BIG}
+         * @return The number of bigs in BIG object
+         */								
         nbits: function() {
             var k = BIG.NLEN - 1,
                 bts, c;
@@ -299,7 +389,12 @@
             return bts;
         },
 
-        /* convert this to string */
+	/**
+         * Convert to string
+         *
+         * @this {BIG}
+         * @return string representation of a BIG number
+         */									
         toString: function() {
             var s = "",
                 len = this.nbits(),
@@ -326,7 +421,13 @@
             return s;
         },
 
-        /* this+=y */
+	/**
+         * Sum two BIG mumbers
+         *
+         * @this {BIG}
+         * @parameter y BIG object
+         * @return this+=y
+         */										
         add: function(y) {
             var i;
 
@@ -338,7 +439,13 @@
         },
 
 
-        /* this|=y */
+	/**
+         * OR two BIG mumbers
+         *
+         * @this {BIG}
+         * @parameter y BIG object
+         * @return this|=y 
+         */										
         or: function(y) {
             var i;
 
@@ -349,8 +456,13 @@
             return this;
         },
 
-
-        /* return this+x */
+	/**
+         * Sum two BIG mumbers
+         *
+         * @this {BIG}
+         * @parameter x BIG object
+         * @return this+x 
+         */										
         plus: function(x) {
             var s = new BIG(0),
                 i;
@@ -362,14 +474,26 @@
             return s;
         },
 
-        /* this+=i, where i is int */
+	/**
+         * Sum BIG and integer
+         *
+         * @this {BIG}
+         * @parameter i Integer to add
+         * @return this+=i
+         */										
         inc: function(i) {
             this.norm();
             this.w[0] += i;
             return this;
         },
 
-        /* this-=y */
+	/**
+         * Subtract BIG from one another
+         *
+         * @this {BIG}
+         * @parameter y BIG object
+         * @return this-=y 
+         */										
         sub: function(y) {
             var i;
 
@@ -380,7 +504,13 @@
             return this;
         },
 
-        /* reverse subtract this=x-this */
+	/**
+         * Reverse subtract BIG from one another
+         *
+         * @this {BIG}
+         * @parameter x BIG object
+         * @return this=x-this
+         */										
         rsub: function(x) {
             var i;
 
@@ -391,14 +521,26 @@
             return this;
         },
 
-        /* this-=i, where i is int */
+	/**
+         * Subtract integer from BIG
+         *
+         * @this {BIG}
+         * @parameter i Integer to subtract
+         * @return this-=i
+         */										
         dec: function(i) {
             this.norm();
             this.w[0] -= i;
             return this;
         },
 
-        /* return this-x */
+	/**
+         * Subtract BIG
+         *
+         * @this {BIG}
+         * @parameter x BIG object
+         * @return New BIG object
+         */
         minus: function(x) {
             var d = new BIG(0),
                 i;
@@ -410,7 +552,13 @@
             return d;
         },
 
-        /* multiply by small integer */
+	/**
+         * Multiply by small integer
+         *
+         * @this {BIG}
+         * @parameter c small integer
+         * @return this*c 
+         */
         imul: function(c) {
             var i;
 
@@ -421,7 +569,11 @@
             return this;
         },
 
-        /* convert this BIG to byte array */
+	/**
+         * convert this BIG to byte array 
+         *
+         * @this {BIG}
+         */
         tobytearray: function(b, n) {
             var c = new BIG(0),
                 i;
@@ -437,19 +589,33 @@
             return this;
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte array 
+         *
+         * @this {BIG}
+         */
         toBytes: function(b) {
             this.tobytearray(b, 0);
         },
 
-        /* set this[i]+=x*y+c, and return high part */
+	/**
+         * this[i]+=x*y+c, and return high part
+         *
+         * @this {BIG}
+         */
         muladd: function(x, y, c, i) {
             var prod = x * y + c + this.w[i];
             this.w[i] = prod & BIG.BMASK;
             return ((prod - this.w[i]) * BIG.MODINV);
         },
 
-        /* multiply by larger int */
+	/**
+         *  multiply by larger int
+         *
+         * @this {BIG}
+         * @parameter c large integer
+         * @return carry value
+         */
         pmul: function(c) {
             var carry = 0,
                 ak, i;
@@ -463,7 +629,13 @@
             return carry;
         },
 
-        /* multiply by still larger int - results requires a ctx.DBIG */
+	/**
+         *  multiply by still larger int - results requires a DBIG
+         *
+         * @this {BIG}
+         * @parameter c large integer
+         * @return DBIG object
+         */
         pxmul: function(c) {
             var m = new ctx.DBIG(0),
                 carry = 0,
@@ -478,7 +650,12 @@
             return m;
         },
 
-        /* divide by 3 */
+	/**
+         *  divide by 3 
+         *
+         * @this {BIG}
+         * @return carry value
+         */
         div3: function() {
             var carry = 0,
                 ak, base, i;
@@ -494,7 +671,13 @@
             return carry;
         },
 
-        /* set x = x mod 2^m */
+	/**
+         * set x = x mod 2^m
+         *
+         * @this {BIG}
+         * @parameter m Exponent
+         * @return BIG object
+         */
         mod2m: function(m) {
             var i, wd, bt, msk;
 
@@ -508,7 +691,12 @@
             }
         },
 
-        /* a=1/a mod 2^256. This is very fast! */
+	/**
+         * a=1/a mod 2^256. This is very fast! 
+         *
+         * @this {BIG}
+         * @return BIG object
+         */
         invmod2m: function() {
             var U = new BIG(0),
                 b = new BIG(0),
@@ -548,7 +736,12 @@
             this.norm();
         },
 
-        /* reduce this mod m */
+	/**
+         * reduce this mod m 
+         *
+         * @this {BIG}
+         * @return BIG object
+         */
         mod: function(m1) {
             var k = 0,
                 r = new BIG(0);
@@ -576,7 +769,14 @@
                 k--;
             }
         },
-        /* this/=m */
+
+	/**
+         * this/=m1
+         *
+         * @this {BIG}
+         * @paramter m1 divisor
+         * @return BIG number
+         */
         div: function(m1) {
             var k = 0,
                 d = 0,
@@ -612,12 +812,24 @@
                 k--;
             }
         },
-        /* return parity of this */
+
+	/**
+         * return parity of this 
+         *
+         * @this {BIG}
+         * @return BIG object
+         */
         parity: function() {
             return this.w[0] % 2;
         },
 
-        /* return n-th bit of this */
+	/**
+         * return n-th bit of this 
+         *
+         * @this {BIG}
+         * @parameter nth bit to return
+         * @return bit value
+         */
         bit: function(n) {
             if ((this.w[Math.floor(n / BIG.BASEBITS)] & (1 << (n % BIG.BASEBITS))) > 0) {
                 return 1;
@@ -626,7 +838,13 @@
             }
         },
 
-        /* return last n bits of this */
+	/**
+         * return last n bits of this 
+         *
+         * @this {BIG}
+         * @parameter n bits to return
+         * @return bit values
+         */
         lastbits: function(n) {
             var msk = (1 << n) - 1;
             this.norm();
@@ -646,7 +864,13 @@
             return ok;
         },
 
-        /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */
+	/**
+         * Jacobi Symbol (this/p)
+         *
+         * @this {BIG}
+         * @parameter p BIG number 
+         * @return 0, 1 or -1 
+         */	
         jacobi: function(p) {
             var m = 0,
                 t = new BIG(0),
@@ -697,7 +921,13 @@
             }
         },
 
-        /* this=1/this mod p. Binary method */
+	/**
+         * this=1/this mod p. Binary method
+         *
+         * @this {BIG}
+         * @parameter p The BIG Modulus
+         * @return BIG object
+         */	
         invmodp: function(p) {
             var u = new BIG(0),
                 v = new BIG(0),
@@ -761,7 +991,14 @@
             }
         },
 
-        /* return this^e mod m */
+	/**
+         * Exponentation modulo m
+         *
+         * @this {BIG}
+         * @parameter e1 BIG number
+         * @parameter m  The BIG Modulus
+         * @return this^e mod m
+         */		
         powmod: function(e1, m) {
             var a = new BIG(1),
                 z = new BIG(0),
@@ -809,7 +1046,13 @@
 		return ((r.w[n]>>(BIG.CHUNK-1))&1);
 	};
 
-    /* convert from byte array to BIG */
+    /**
+     * convert from byte array to BIG 
+     *
+     * @this {BIG}
+     * @parameter b Bytearray
+     * @return BIG object
+     */	
     BIG.frombytearray = function(b, n) {
         var m = new BIG(0),
             i;
@@ -826,7 +1069,14 @@
         return BIG.frombytearray(b, 0);
     };
 
-    /* return a*b where product fits a BIG */
+    /**
+     * return a*b where product fits a BIG 
+     *
+     * @this {BIG}
+     * @parameter a BIG number
+     * @parameter b BIG number
+     * @return a*b
+     */	    
     BIG.smul = function(a, b) {
         var c = new BIG(0),
             carry, i, j;
@@ -844,7 +1094,14 @@
         return c;
     };
 
-    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    /**
+     * Compare a and b
+     *
+     * @this {BIG}
+     * @parameter a BIG number (normalised)
+     * @parameter b BIG number (normalised
+     * @return 0 if a==b, -1 if a<b, +1 if a>b
+     */	        
     BIG.comp = function(a, b) {
         var i;
 
@@ -863,7 +1120,13 @@
         return 0;
     };
 
-    /* get 8*MODBYTES size random number */
+    /**
+     * Get 8*MODBYTES size random number 
+     *
+     * @this {BIG}
+     * @parameter rng Cryptographically Secure Random Number Generator
+     * @return BIG number
+     */	            
     BIG.random = function(rng) {
         var m = new BIG(0),
             j = 0,
@@ -887,7 +1150,14 @@
         return m;
     };
 
-    /* Create random BIG in portable way, one bit at a time */
+    /**
+     * Create random BIG in portable way, one bit at a time 
+     *
+     * @this {BIG}
+     * @parameter rng Cryptographically Secure Random Number Generator
+     * @parameter q The BIG Modulus
+     * @return BIG number
+     */	                
     BIG.randomnum = function(q, rng) {
         var d = new ctx.DBIG(0),
             j = 0,
@@ -913,7 +1183,14 @@
         return m;
     };
 
-    /* return a*b as ctx.DBIG */
+    /**
+     * Multiple two BIG numbers
+     *
+     * @this {BIG}
+     * @parameter a BIG number
+     * @parameter b BIG number
+     * @return a*b as a DBIG number
+     */	                
     BIG.mul = function(a, b) {
         var c = new ctx.DBIG(0),
             d = new Array(BIG.NLEN), //[],
@@ -955,7 +1232,13 @@
         return c;
     };
 
-    /* return a^2 as ctx.DBIG */
+    /**
+     * Square two BIG numbers
+     *
+     * @this {BIG}
+     * @parameter a BIG number
+     * @return a*2 as a DBIG number
+     */	                    
     BIG.sqr = function(a) {
         var c = new ctx.DBIG(0),
             n, t, j, i, co;
@@ -1057,7 +1340,15 @@
         return b;
     };
 
-    /* return a*b mod m */
+    /**
+     * Multiple two BIG numbers modulo m
+     *
+     * @this {BIG}
+     * @parameter a1 BIG number
+     * @parameter b1 BIG number
+     * @parameter m The BIG Modulus
+     * @return a1*b1 mod m  as a BIG number
+     */	                    
     BIG.modmul = function(a1, b1, m) {
         var d;
 		var a=new BIG(0); a.copy(a1);
@@ -1069,7 +1360,14 @@
         return d.mod(m);
     };
 
-    /* return a^2 mod m */
+    /**
+     * Square a BIG number modulo m
+     *
+     * @this {BIG}
+     * @parameter a1 BIG number
+     * @parameter m The BIG Modulus
+     * @return a*2 mod m  as a BIG number
+     */	                        
     BIG.modsqr = function(a1, m) {
         var d;
 		var a=new BIG(0); a.copy(a1);
@@ -1079,14 +1377,27 @@
         return d.mod(m);
     };
 
-    /* return -a mod m */
+    /**
+     * Inversion
+     *
+     * @this {BIG}
+     * @parameter a1 BIG number
+     * @parameter m The BIG Modulus
+     * @return -a1 mod m
+     */	                            
     BIG.modneg = function(a1, m) {
 		var a=new BIG(0); a.copy(a1);
         a.mod(m);
         return m.minus(a);
     };
 
-    /* Arazi and Qi inversion mod 256 */
+    /**
+     *  Arazi and Qi inversion mod 256
+     *
+     * @this {BIG}
+     * @parameter a BIG number
+     * @return BIG number
+     */	                                
     BIG.invmod256 = function(a) {
         var U, t1, t2, b, c;
 
@@ -1133,7 +1444,12 @@
 DBIG = function(ctx) {
     "use strict";
 
-    /* constructor */
+    /**
+     * General purpose Constructor 
+     *
+     * @constructor
+     * @this {DBIG}
+     */        
     var DBIG = function(x) {
         this.w = new Array(BIG.DNLEN);
         this.zero();
@@ -1142,7 +1458,12 @@
 
     DBIG.prototype = {
 
-        /* set this=0 */
+	/**
+         * set to zero
+         *
+         * @this {DBIG}
+         * @return BIG number
+         */
         zero: function() {
             for (var i = 0; i < ctx.BIG.DNLEN; i++) {
                 this.w[i] = 0;
@@ -1150,7 +1471,13 @@
             return this;
         },
 
-        /* set this=b */
+	/**
+         * set to b
+         *
+         * @this {DBIG}
+         * @parameter b DBIG number 
+         * @return DBIG number
+         */		
         copy: function(b) {
             for (var i = 0; i < ctx.BIG.DNLEN; i++) {
                 this.w[i] = b.w[i];
@@ -1158,8 +1485,13 @@
             return this;
         },
 
-
-        /* copy from ctx.BIG */
+	/**
+         * copy from ctx.BIG 
+         *
+         * @this {DBIG}
+         * @parameter b BIG number 
+         * @return DBIG number
+         */			
         hcopy: function(b) {
             var i;
 
@@ -1188,7 +1520,12 @@
             return this;
         },
 
-        /* normalise this */
+	/**
+         *  normalise DBIG - force all digits < 2^BASEBITS 
+         *
+         * @this {DBIG}
+         * @return DBIG number
+         */						
         norm: function() {
             var carry = 0,
                 d, i;
@@ -1203,14 +1540,24 @@
             return this;
         },
 
-        /* set this[i]+=x*y+c, and return high part */
+	/**
+         * this[i]+=x*y+c, and return high part
+         *
+         * @this {DBIG}
+         */	
         muladd: function(x, y, c, i) {
             var prod = x * y + c + this.w[i];
             this.w[i] = prod & ctx.BIG.BMASK;
             return ((prod - this.w[i]) * ctx.BIG.MODINV);
         },
 
-        /* shift this right by k bits */
+	/**
+         * General shift right by k bits 
+         *
+         * @this {DBIG}
+         * @parameter k Number of bits to shift
+         * @return BIG number
+         */							
         shr: function(k) {
             var n = k % ctx.BIG.BASEBITS,
                 m = Math.floor(k / ctx.BIG.BASEBITS),
@@ -1229,7 +1576,13 @@
             return this;
         },
 
-        /* shift this left by k bits */
+	/**
+         * General shift left by k bits
+         *
+         * @this {BIG}
+         * @parameter k Number of bits to shift
+         * @return BIG number 
+         */							
         shl: function(k) {
             var n = k % ctx.BIG.BASEBITS,
                 m = Math.floor(k / ctx.BIG.BASEBITS),
@@ -1250,7 +1603,13 @@
             return this;
         },
 
-        /* Conditional move of ctx.BIG depending on d using XOR - no branches */
+	/**
+         * Conditional move of BIG depending on d using XOR - no branches 
+         *
+         * @this {DBIG}
+         * @parameter b DBIG number 
+         * @parameter d DBIG number 
+         */			
         cmove: function(b, d) {
             var c = d,
                 i;
@@ -1262,14 +1621,26 @@
             }
         },
 
-        /* this+=x */
+	/**
+         * Sum two DBIG mumbers
+         *
+         * @this {DBIG}
+         * @parameter x DBIG object
+         * @return this+=x
+         */											
         add: function(x) {
             for (var i = 0; i < ctx.BIG.DNLEN; i++) {
                 this.w[i] += x.w[i];
             }
         },
 
-        /* this-=x */
+	/**
+         * Subtract DBIG from one another
+         *
+         * @this {DBIG}
+         * @parameter x BIG object
+         * @return this-=x 
+         */											
         sub: function(x) {
             for (var i = 0; i < ctx.BIG.DNLEN; i++) {
                 this.w[i] -= x.w[i];
@@ -1282,7 +1653,12 @@
             }
         },
 
-        /* return number of bits in this */
+	/**
+         * length in bits 
+         *
+         * @this {DBIG}
+         * @return The number of bigs in DBIG object
+         */									
         nbits: function() {
             var k = ctx.BIG.DNLEN - 1,
                 bts, c;
@@ -1309,7 +1685,12 @@
             return bts;
         },
 
-        /* convert this to string */
+	/**
+         * Convert to string
+         *
+         * @this {DBIG}
+         * @return string representation of a BIG number
+         */									
         toString: function() {
             var s = "",
                 len = this.nbits(),
@@ -1332,7 +1713,12 @@
             return s;
         },
 
-        /* reduces this DBIG mod a ctx.BIG, and returns the ctx.BIG */
+	/**
+         * reduces this DBIG mod a ctx.BIG, and returns the ctx.BIG 
+         *
+         * @this {DBIG}
+         * @return BIG object
+         */	
         mod: function(c) {
             var k = 0,
                 m = new DBIG(0),
@@ -1367,7 +1753,13 @@
             return r;
         },
 
-        /* this/=c */
+	/**
+         * this/=c
+         *
+         * @this {DBIG}
+         * @paramter c divisor
+         * @return DBIG number
+         */	
         div: function(c) {
             var d = 0,
                 k = 0,
@@ -1405,7 +1797,13 @@
             return a;
         },
 
-        /* split this DBIG at position n, return higher half, keep lower half */
+	/**
+         * split this DBIG at position n, return higher half, keep lower half 
+         *
+         * @this {DBIG}
+         * @paramter n Position to splitdivisor
+         * @return lower half BIG number
+         */	
         split: function(n) {
             var t = new ctx.BIG(0),
                 m = n % ctx.BIG.BASEBITS,
@@ -1425,7 +1823,14 @@
 
     };
 
-    /* Compare a and b, return 0 if a==b, -1 if a<b, +1 if a>b. Inputs must be normalised */
+    /**
+     * Compare a and b
+     *
+     * @this {DBIG}
+     * @parameter a DBIG number (normalised)
+     * @parameter b DBIG number (normalised
+     * @return 0 if a==b, -1 if a<b, +1 if a>b
+     */	            
     DBIG.comp = function(a, b) {
         var i;
 
diff --git a/src/bls.js b/src/bls.js
index b65e54e..468f94a 100644
--- a/src/bls.js
+++ b/src/bls.js
@@ -22,6 +22,12 @@
 var BLS = function(ctx) {
     "use strict";
 
+    /**
+     * Creates an instance of BLS
+     *
+     * @constructor
+     * @this {BLS}
+     */        
     var BLS = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -29,6 +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,
@@ -44,6 +57,13 @@
             return s;
         },
 
+       /**
+         * Convert string to byte array 
+         *
+         * @this {BLS}
+         * @parameter s string
+         * @return byte array
+         */			
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -55,8 +75,14 @@
             return b;
         },
 
-/* hash a message to an ECP point, using SHA3 */
 
+        /**
+          *  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 hm = [];
@@ -68,9 +94,16 @@
 			return P;
 		},
 
-/* generate key pair, private key S, public key W */
-
-		KeyPairGenerate(rng,S,W) {
+	/**
+          * 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);
@@ -82,9 +115,16 @@
 			return this.BLS_OK;
 		},
 
-/* Sign message m using private key S to produce signature SIG */
-
-		sign(SIG,m,S) {
+	/**
+          * 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);
@@ -92,9 +132,16 @@
 			return this.BLS_OK;
 		},
 
-/* Verify signature given message m, the signature SIG, and the public key W */
-
-		verify(SIG,m,W) {
+	/**
+          * 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();
@@ -116,8 +163,16 @@
 			return this.BLS_FAIL;
 		},
 
-	        /* R=R1+R2 in group G1 */
-                add_G1(R1, R2, R) {
+	/**
+          * 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);
 
@@ -132,8 +187,16 @@
                        return 0;
                 },
 
-                /* W=W1+W2 in group G2 */
-                add_G2(W1, W2, W) {
+ 	/**
+          *  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);
 
diff --git a/src/bls192.js b/src/bls192.js
index a2e3e01..4c46501 100644
--- a/src/bls192.js
+++ b/src/bls192.js
@@ -21,7 +21,13 @@
 
 var BLS192 = function(ctx) {
     "use strict";
-
+    
+    /**
+     * Creates an instance of BLS192
+     *
+     * @constructor
+     * @this {BLS192}
+    */
     var BLS192 = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -29,6 +35,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,
@@ -44,6 +57,13 @@
             return s;
         },
 
+       /**
+         * Convert string to byte array 
+         *
+         * @this {BLS192}
+         * @parameter s string
+         * @return byte array
+         */	
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -55,12 +75,17 @@
             return b;
         },
 
-/* hash a message to an ECP point, using SHA3 */
-
+        /**
+          *  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);
+                        var hm = [];
+                        var t=this.stringtobytes(m);
 			for (var i=0;i<t.length;i++)
 				sh.process(t[i]);
 			sh.shake(hm,this.BFS);
@@ -68,13 +93,20 @@
 			return P;
 		},
 
-/* generate key pair, private key S, public key W */
-
-		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);
+	/**
+          * 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 
@@ -82,19 +114,34 @@
 
 		},
 
-/* Sign message m using private key S to produce signature SIG */
+	/**
+          * 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);
 
-		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;
-		},
+	        D.toBytes(SIG,true);
+		return this.BLS_OK;
+	},
 
-/* Verify signature given message m, the signature SIG, and the public key W */
-
-		verify(SIG,m,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.ECP4.generator();
@@ -115,8 +162,16 @@
 			return this.BLS_FAIL;
 		},
 
-	        /* R=R1+R2 in group G1 */
-                add_G1(R1, R2, R) {
+	/**
+          * 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);
 
@@ -129,10 +184,18 @@
                        P.toBytes(R,true);
 
                        return 0;
-                },
+        },
 
-                /* W=W1+W2 in group G2 */
-                add_G2(W1, W2, W) {
+	/**
+          *  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);
 
diff --git a/src/bls256.js b/src/bls256.js
index f48f4e9..269765d 100644
--- a/src/bls256.js
+++ b/src/bls256.js
@@ -22,6 +22,12 @@
 var BLS256 = function(ctx) {
     "use strict";
 
+    /**
+     * Creates an instance of BLS256
+     *
+     * @constructor
+     * @this {BLS256}
+     */    
     var BLS256 = {
         BLS_OK: 0,
         BLS_FAIL: -1,
@@ -29,6 +35,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,
@@ -44,6 +57,13 @@
             return s;
         },
 
+       /**
+         * Convert string to byte array 
+         *
+         * @this {BLS192}
+         * @parameter s string
+         * @return byte array
+         */		
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -55,8 +75,13 @@
             return b;
         },
 
-/* hash a message to an ECP point, using SHA3 */
-
+        /**
+          *  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 = [];
@@ -68,9 +93,16 @@
 			return P;
 		},
 
-/* generate key pair, private key S, public key W */
-
-		KeyPairGenerate(rng,S,W) {
+	/**
+          * 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);
@@ -82,9 +114,16 @@
 
 		},
 
-/* Sign message m using private key S to produce signature SIG */
-
-		sign(SIG,m,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);
@@ -92,9 +131,16 @@
 			return this.BLS_OK;
 		},
 
-/* Verify signature given message m, the signature SIG, and the public key W */
-
-		verify(SIG,m,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();
@@ -117,8 +163,16 @@
 		},
 
 
-	        /* R=R1+R2 in group G1 */
-                add_G1(R1, R2, R) {
+	/**
+          * 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);
 
@@ -133,8 +187,16 @@
                        return 0;
                 },
 
-                /* W=W1+W2 in group G2 */
-                add_G2(W1, W2, W) {
+	/**
+          *  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);
 
diff --git a/src/ecdh.js b/src/ecdh.js
index 416c74c..43a3b0b 100644
--- a/src/ecdh.js
+++ b/src/ecdh.js
@@ -20,6 +20,12 @@
 var ECDH = function(ctx) {
     "use strict";
 
+    /**
+     * Creates an instance of ECDH
+     *
+     * @constructor
+     * @this {ECDH}
+    */    
     var ECDH = {
 
         INVALID_PUBLIC_KEY: -2,
@@ -31,7 +37,14 @@
         SHA384: 48,
         SHA512: 64,
 
-        /* Convert Integer to n-byte array */
+	/**
+         * Convert Integer to n-byte array 
+         *
+         * @this {ECDH}
+         * @parameter n integer
+         * @parameter len integer length
+         * @return byte array
+         */		
         inttobytes: function(n, len) {
             var b = [],
                 i;
@@ -50,6 +63,13 @@
             return b;
         },
 
+        /**
+          * Convert byte array to string
+          *
+          * @this {ECDH}
+          * @parameter b byte array
+          * @return string
+          */			
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -64,6 +84,13 @@
             return s;
         },
 
+       /**
+         * Convert string to byte array 
+         *
+         * @this {ECDH}
+         * @parameter s string
+         * @return byte array
+         */				
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -75,6 +102,16 @@
             return b;
         },
 
+        /**
+          *  general purpose hash function w=hash(B|n)
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter A byte array involved in the hash
+	  * @parameter n integer involved in the hash
+          * @parameter pad padding
+  	  * @return w output
+          */		
         hashit: function(sha, A, n, B, pad) {
             var R = [],
                 H, W, i, len;
@@ -124,6 +161,7 @@
             return W;
         },
 
+	
         KDF1: function(sha, Z, olen) {
             /* NOTE: the parameter olen is the length of the output K in bytes */
             var hlen = sha,
@@ -158,6 +196,16 @@
             return K;
         },
 
+        /**
+          * IEEE-1363 Key Derivation Function - generates key K from inputs Z and P
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter Z input byte array
+	  * @parameter P input key derivation parameters - can be NULL
+          * @parameter 0len is output desired length of key
+  	  * @return K derived key
+          */			
         KDF2: function(sha, Z, P, olen) {
             /* NOTE: the parameter olen is the length of the output k in bytes */
             var hlen = sha,
@@ -192,10 +240,17 @@
             return K;
         },
 
-        /* Password based Key Derivation Function */
-        /* Input password p, salt s, and repeat count */
-        /* Output key of length olen */
-
+	/**
+          * Password Based Key Derivation Function - generates key K from password, salt and repeat counter
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter Pass input password
+	  * @parameter Salt salt value
+          * @parameter rep Number of times to be iterated.
+          * @parameter 0len is output desired length of key
+  	  * @return key derived key
+          */			
         PBKDF2: function(sha, Pass, Salt, rep, olen) {
             var F = new Array(sha),
                 U = [],
@@ -249,6 +304,16 @@
             return key;
         },
 
+	/**
+          * HMAC of message M using key K to create tag of length tag.length
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter M input message
+	  * @parameter K input encryption key
+          * @parameter tag is the output HMAC
+  	  * @return error code
+          */				
         HMAC: function(sha, M, K, tag) {
             /* Input is from an octet m        *
              * olen is requested output length in bytes. k is the key  *
@@ -303,8 +368,14 @@
             return 1;
         },
 
-        /* ctx.AES encryption/decryption */
-
+	/**
+          * AES encrypts a plaintext to a ciphtertext
+          *
+          * @this {ECDH}
+	  * @parameter M input message
+	  * @parameter K AES key
+  	  * @return C Ciphertext
+          */				
         AES_CBC_IV0_ENCRYPT: function(K, M) { /* ctx.AES CBC encryption, with Null IV and key K */
             /* Input is from an octet string M, output is to an octet string C */
             /* Input is padded as necessary to make up a full final block */
@@ -354,6 +425,14 @@
             return C;
         },
 
+	/**
+          * AES encrypts a plaintext to a ciphtertext
+          *
+          * @this {ECDH}
+	  * @parameter C Ciphertext
+	  * @parameter K AES key
+  	  * @return P Plaintext
+          */					
         AES_CBC_IV0_DECRYPT: function(K, C) { /* padding is removed */
             var a = new ctx.AES(),
                 buff = [],
@@ -425,6 +504,15 @@
             return M;
         },
 
+	/**
+          * Generate an ECC public/private key pair
+          *
+          * @this {ECDH}
+          * @parameter rng Cryptographically Secure Random Number Generator
+	  * @parameter S the private key
+	  * @parameter W the output public key, which is s.G, where G is a fixed generator
+  	  * @return 0 or an error code
+          */						
         KEY_PAIR_GENERATE: function(RNG, S, W) {
             var res = 0,
                 r, s, G, WP;
@@ -450,6 +538,13 @@
             return res;
         },
 
+	/**
+          * Generate an ECC public/private key pair
+          *
+          * @this {ECDH}
+	  * @parameter W the input public key to be validated
+  	  * @return 0 or an error code
+          */					
         PUBLIC_KEY_VALIDATE: function(W) {
             var WP = ctx.ECP.fromBytes(W),
                 res = 0,
@@ -488,6 +583,15 @@
             return res;
         },
 
+	/**
+          * Generate Diffie-Hellman shared key
+          *
+          * @this {ECDH}
+	  * @parameter S the private key
+	  * @parameter W the output public key, which is s.G, where G is a fixed generator
+	  * @parameter K the output shared key, in fact the x-coordinate of s.W
+  	  * @return 0 or an error code
+          */							
         ECPSVDP_DH: function(S, WD, Z) {
             var T = [],
                 res = 0,
@@ -520,6 +624,18 @@
             return res;
         },
 
+	/**
+          * ECDSA Signature
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+          * @parameter RNG Cryptographically Secure Random Number Generator
+	  * @parameter S the private key
+	  * @parameter F the input message to be signed
+	  * @parameter C component of the output signature
+	  * @parameter D component of the output signature
+  	  * @return 0 or an error code
+          */								
         ECPSP_DSA: function(sha, RNG, S, F, C, D) {
             var T = [],
                 i, r, s, f, c, d, u, vx, w,
@@ -570,6 +686,17 @@
             return 0;
         },
 
+	/**
+          * ECDSA Signature Verification
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter W the public key
+	  * @parameter F the input message to be signed
+	  * @parameter C component of the output signature
+	  * @parameter D component of the output signature
+  	  * @return 0 or an error code
+          */									
         ECPVP_DSA: function(sha, W, F, C, D) {
             var B = [],
                 res = 0,
@@ -619,6 +746,20 @@
             return res;
         },
 
+	/**
+          * ECIES Encryption
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter P1 input Key Derivation parameters
+	  * @parameter P2 input Encoding parameters
+          * @parameter RNG Cryptographically Secure Random Number Generator
+	  * @parameter W the public key
+	  * @parameter M the input message to be encrypted
+	  * @parameter V component of the output ciphertext
+	  * @parameter T the output HMAC tag, part of the ciphertext
+  	  * @return C ciphertext
+          */										
         ECIES_ENCRYPT: function(sha, P1, P2, RNG, W, M, V, T) {
             var Z = [],
                 VZ = [],
@@ -681,6 +822,19 @@
 			return false;
 		},
 
+	/**
+          * ECIES Encryption
+          *
+          * @this {ECDH}
+          * @parameter sha is the hash type
+	  * @parameter P1 input Key Derivation parameters
+	  * @parameter P2 input Encoding parameters
+	  * @parameter V component of the output ciphertext
+          * @parameter C Ciphertext
+	  * @parameter T the output HMAC tag, part of the ciphertext
+	  * @parameter U the private key
+  	  * @return M plaintext
+          */											
         ECIES_DECRYPT: function(sha, P1, P2, V, C, T, U) {
             var Z = [],
                 VZ = [],
diff --git a/src/ecp.js b/src/ecp.js
index e6c078e..db556d2 100644
--- a/src/ecp.js
+++ b/src/ecp.js
@@ -22,7 +22,12 @@
 var ECP = function(ctx) {
     "use strict";
 
-    /* Constructor */
+    /**
+     * Creates an instance of ECP
+     *
+     * @constructor
+     * @this {ECP}
+     */    
     var ECP = function(input) {
         if (input instanceof ECP) {
             // copy constructor
@@ -62,7 +67,13 @@
     ECP.AESKEY = ctx.config["@AK"];
 
     ECP.prototype = {
-        /* test this=O point-at-infinity */
+	
+	/**
+         * Tests for ECP point equal to infinity
+         *
+         * @this {ECP}
+         * @param 1 if infinity, else returns 0
+         */	
         is_infinity: function() {
   
             this.x.reduce();
@@ -83,7 +94,12 @@
             return true;
         },
 
-        /* conditional swap of this and Q dependant on d */
+
+	/**
+         * conditional swap of this and Q dependant on dCopy ECP point to another ECP point
+         *
+         * @this {ECP}
+         */	
         cswap: function(Q, d) {
 
             this.x.cswap(Q.x, d);
@@ -94,7 +110,11 @@
 
         },
 
-        /* conditional move of Q to P dependant on d */
+	/**
+         * conditional move of Q to P dependant on d 
+         *
+         * @this {ECP}
+         */	
         cmove: function(Q, d) {
 
             this.x.cmove(Q.x, d);
@@ -105,7 +125,11 @@
 
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {ECP}
+         */	
         select: function(W, b) {
             var MP = new ECP(),
                 m = b >> 31,
@@ -160,7 +184,12 @@
             return true;
         },
 
-        /* copy this=P */
+	/**
+         * Copy ECP point to another ECP point
+         *
+         * @this {ECP}
+         * @param P ECP instance
+         */	
         copy: function(P) {
             this.x.copy(P.x);
             if (ECP.CURVETYPE != ECP.MONTGOMERY) {
@@ -169,7 +198,11 @@
             this.z.copy(P.z);
         },
 
-        /* this=-this */
+	/**
+         * set this=-this 
+         *
+         * @this {ECP}
+         */	
         neg: function() {
             if (ECP.CURVETYPE == ECP.WEIERSTRASS) {
                 this.y.neg();
@@ -182,7 +215,11 @@
             return;
         },
 
-        /* set this=O */
+	/**
+         * Set ECP to point-at-infinity
+         *
+         * @this {ECP}
+         */	
         inf: function() {
             this.x.zero();
 
@@ -197,7 +234,13 @@
             }
         },
 
-        /* set this=(x,y) where x and y are BIGs */
+	/**
+         * set this=(x,y)
+         *
+         * @this {ECP}
+         * @param ix x-value
+         * @param iy y-value
+         */	
         setxy: function(ix, iy) {
             var rhs, y2;
 
@@ -226,7 +269,13 @@
             }
         },
 
-        /* set this=x, where x is ctx.BIG, y is derived from sign s */
+	/**
+         * set this=x, where x is ctx.BIG, y is derived from sign s 
+         *
+         * @this {ECP}
+         * @param ix x-value
+         * @param s sign to derive y
+         */	
         setxi: function(ix, s) {
             var rhs, ny;
 
@@ -247,7 +296,13 @@
             }
         },
 
-        /* set this=x, y calculated from curve equation */
+	/**
+         * 	
+         * set this=x, y calculated from curve equation 
+         *
+         * @this {ECP}
+         * @param ix x-value
+         */	
         setx: function(ix) {
             var rhs;
 
@@ -266,7 +321,11 @@
             }
         },
 
-        /* set this to affine - from (x,y,z) to (x,y) */
+	/**
+         * convert this to affine, from (x,y,z) to (x,y) 
+         *
+         * @this {ECP}
+         */	
         affine: function() {
             var one;
 
@@ -296,40 +355,69 @@
             }
         },
 
-        /* extract x as ctx.BIG */
+	/**
+         * extract affine x as ctx.FP2 
+         *
+         * @this {ECP}
+         */	
         getX: function() {
 			var W=new ECP(); W.copy(this); W.affine();
             return W.x.redc();
         },
 
-        /* extract y as ctx.BIG */
+	/**
+         * extract affine y as ctx.FP2
+         *
+         * @this {ECP}
+         */	
         getY: function() {
 			var W=new ECP(); W.copy(this); W.affine();
             return W.y.redc();
         },
 
-        /* get sign of Y */
+	/**
+         * get sign of Y 
+         *
+         * @this {ECP}
+         */	
         getS: function() {
             var y = this.getY();
             return y.parity();
         },
 
-        /* extract x as ctx.FP */
+	/**
+         * extract x as ctx.FP 
+         *
+         * @this {ECP}
+         */	
         getx: function() {
             return this.x;
         },
 
-        /* extract y as ctx.FP */
+	/**
+         * extract y as ctx.FP
+         *
+         * @this {ECP}
+         */	
         gety: function() {
             return this.y;
         },
 
-        /* extract z as ctx.FP */
+	/**
+         * extract z as ctx.FP
+         *
+         * @this {ECP}
+         */	
         getz: function() {
             return this.z;
         },
 
-        /* convert to byte array */
+	/**
+         * convert this to byte arrayextract projective x
+         *
+         * @this {ECP}
+         * @param b byte array output
+         */	
         toBytes: function(b,compress) {
             var t = [],
                 i;
@@ -361,7 +449,13 @@
                 b[i + ctx.BIG.MODBYTES + 1] = t[i];
             }
         },
-        /* convert to hex string */
+
+	/**
+         * convert this to hex string 
+         *
+         * @this {ECP}
+         * @return hex string
+         */	
         toString: function() {
 			var W=new ECP(); W.copy(this);
             if (W.is_infinity()) {
@@ -377,7 +471,11 @@
             }
         },
 
-        /* this+=this */
+	/**
+         * this+=this 
+         *
+         * @this {ECP}
+         */	
         dbl: function() {
             var t0, t1, t2, t3, x3, y3, z3, b,
                 C, D, H, J,
@@ -600,7 +698,12 @@
             return;
         },
 
-        /* this+=Q */
+	/**
+         * Adds ECP instances
+         *
+         * param Q ECP instance
+         * @this {ECP}
+         */		
         add: function(Q) {
             var b, t0, t1, t2, t3, t4, x3, y3, z3,
                 A, B, C, D, E, F, G;
@@ -936,14 +1039,25 @@
             //  this.x.norm();
         },
 
-        /* this-=Q */
+	/**
+         * Subtracts ECP instance Q  from this
+         *
+         * @this {ECP}
+         * @param Q ECP instance
+         */	
         sub: function(Q) {
 			var NQ = new ECP(); NQ.copy(Q);
             NQ.neg();
             this.add(NQ);
         },
 
-        /* constant time multiply by small integer of length bts - use ladder */
+	/**
+         * constant time multiply by small integer of length bts - use ladder 
+         *
+         * @this {ECP}
+         * @param e small integer
+         * @param bts e bit length
+         */	
         pinmul: function(e, bts) {
             var i, b, P, R0, R1;
 
@@ -972,7 +1086,11 @@
             }
         },
 
-        // multiply this by the curves cofactor
+	/**
+         * multiply this by the curves cofactor
+         *
+         * @this {ECP}
+         */	
         cfp: function() {
             var cf=ctx.ROM_CURVE.CURVE_Cof_I,
                 c = new ctx.BIG(0);
@@ -992,7 +1110,12 @@
         },
 
 
-        /* return e.this - SPA immune, using Ladder */
+	/**
+         * Multiplies an ECP instance P by a BIG, side-channel resistant
+         *
+         * @this {ECP}
+         * @param e BIG number multiplier
+         */		
         mul: function(e) {
             var P, D, R0, R1, mt, t, Q, C, W, w,
                 i, b, nb, s, ns;
@@ -1086,8 +1209,14 @@
             return P;
         },
 
-        /* Return e.this+f.Q */
-
+	/**
+         * Return e.this+f.Q 
+         *
+         * @this {ECP}
+         * @param e BIG number multiplier
+         * @param Q ECP instance
+         * @param f BIG number multiplier
+         */		
         mul2: function(e, Q, f) {
             var te = new ctx.BIG(),
                 tf = new ctx.BIG(),
@@ -1190,7 +1319,11 @@
         }
     };
 
-    // set to group generator
+    /**
+      * Set group generator
+      *
+      * @this {ECP}
+      */	
     ECP.generator = function() {
         var G=new ECP(),
             gx = new ctx.BIG(0),
@@ -1214,7 +1347,12 @@
         return ((x >> 31) & 1);
     };
 
-    /* convert from byte array to ECP */
+    /**
+      * convert from byte array to point 
+      *
+      * @this {ECP}
+      * @param b input byte array
+      */	    
     ECP.fromBytes = function(b) {
         var t = [],
             P = new ECP(),
@@ -1261,7 +1399,12 @@
         return P;
     };
 
-    /* Calculate RHS of curve equation */
+    /**
+      * Calculate RHS of the curve equation 
+      *
+      * @this {ECP}
+      * @param x x-value
+      */	    
     ECP.RHS = function(x) {
         var r = new ctx.FP(0),
             b, cx, one, x3;
diff --git a/src/ecp2.js b/src/ecp2.js
index a813edd..98f2cf0 100644
--- a/src/ecp2.js
+++ b/src/ecp2.js
@@ -22,7 +22,12 @@
 var ECP2 = function(ctx) {
     "use strict";
 
-    /* Constructor */
+    /**
+     * Creates an instance of ECP2
+     *
+     * @constructor
+     * @this {ECP2}
+     */    
     var ECP2 = function(input) {
         if (input instanceof ECP2) {
             // copy constructor
@@ -38,7 +43,13 @@
     };
 
     ECP2.prototype = {
-        /* Test this=O? */
+	
+	/**
+         * Tests for ECP2 point equal to infinity
+         *
+         * @this {ECP2}
+         * @param 1 if infinity, else returns 0
+         */	
         is_infinity: function() {
 
             this.x.reduce();
@@ -47,28 +58,45 @@
             return (this.x.iszilch() && this.z.iszilch());
         },
 
-        /* copy this=P */
+	/**
+         * Copy ECP2 point to another ECP2 point
+         *
+         * @this {ECP2}
+         * @param P ECP2 instance
+         */	
         copy: function(P) {
             this.x.copy(P.x);
             this.y.copy(P.y);
             this.z.copy(P.z);
         },
 
-        /* set this=O */
+	/**
+         * Set ECP2 to point-at-infinity
+         *
+         * @this {ECP2}
+         */	
         inf: function() {
             this.x.zero();
             this.y.one();
             this.z.zero();
         },
 
-        /* conditional move of Q to P dependant on d */
+	/**
+         * conditional move of Q to P dependant on d 
+         *
+         * @this {ECP2}
+         */	
         cmove: function(Q, d) {
             this.x.cmove(Q.x, d);
             this.y.cmove(Q.y, d);
             this.z.cmove(Q.z, d);
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {ECP2}
+         */	
         select: function(W, b) {
             var MP = new ECP2(),
                 m, babs;
@@ -91,7 +119,12 @@
             this.cmove(MP, (m & 1));
         },
 
-        /* Test P == Q */
+	/**
+         * Test P == Q 
+         *
+         * @this {ECP2}
+         * @param Q ECP2 instance 
+         */	
         equals: function(Q) {
             var a, b;
 
@@ -123,7 +156,11 @@
             return true;
         },
 
-        /* set this=-this */
+	/**
+         * set this=-this 
+         *
+         * @this {ECP2}
+         */	
         neg: function() {
             this.y.norm();
             this.y.neg();
@@ -131,7 +168,11 @@
             return;
         },
 
-        /* convert this to affine, from (x,y,z) to (x,y) */
+	/**
+         * convert this to affine, from (x,y,z) to (x,y) 
+         *
+         * @this {ECP2}
+         */	
         affine: function() {
             var one;
 
@@ -156,34 +197,60 @@
             this.z.copy(one);
         },
 
-        /* extract affine x as ctx.FP2 */
+	/**
+         * extract affine x as ctx.FP2 
+         *
+         * @this {ECP2}
+         */	
         getX: function() {
 			var W=new ECP2(); W.copy(this); W.affine();
             return W.x;
         },
 
-        /* extract affine y as ctx.FP2 */
+  
+	/**
+         * extract affine y as ctx.FP2
+         *
+         * @this {ECP2}
+         */	
         getY: function() {
 			var W=new ECP2(); W.copy(this); W.affine();
             return W.y;
         },
 
-        /* extract projective x */
+	/**
+         * extract projective x
+         *
+         * @this {ECP2}
+         */	
         getx: function() {
             return this.x;
         },
 
-        /* extract projective y */
+	/**
+         * extract projective y
+         *
+         * @this {ECP2}
+         */	
         gety: function() {
             return this.y;
         },
 
-        /* extract projective z */
+	/**
+         * extract projective z
+         *
+         * @this {ECP2}
+         */	
         getz: function() {
             return this.z;
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte arrayextract projective x
+         *
+         * @this {ECP2}
+         * @param b byte array output
+         */	
         toBytes: function(b) {
             var t = [],
                 i;
@@ -208,7 +275,12 @@
             }
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string 
+         *
+         * @this {ECP2}
+         * @return hex string
+         */	
         toString: function() {
 			var W=new ECP2(); W.copy(this);
             if (W.is_infinity()) {
@@ -218,7 +290,14 @@
             return "(" + W.x.toString() + "," + W.y.toString() + ")";
         },
 
-        /* set this=(x,y) */
+ 
+	/**
+         * set this=(x,y)
+         *
+         * @this {ECP2}
+         * @param ix x-value
+         * @param iy y-value
+         */	
         setxy: function(ix, iy) {
             var rhs, y2;
 
@@ -237,7 +316,12 @@
             }
         },
 
-        /* set this=(x,.) */
+	/**
+         * set this=(x,.) 
+         *
+         * @this {ECP2}
+         * @param ix x-value
+         */	
         setx: function(ix) {
             var rhs;
 
@@ -254,7 +338,11 @@
             }
         },
 
-        /* set this*=q, where q is Modulus, using Frobenius */
+	/**
+         * set this*=q, where q is Modulus, using Frobenius 
+         *
+         * @this {ECP2}
+         */	
         frob: function(X) {
             var X2;
 
@@ -269,7 +357,11 @@
             this.y.mul(X);
         },
 
-        /* this+=this */
+	/**
+         * this+=this 
+         *
+         * @this {ECP2}
+         */	
         dbl: function() {
             var iy, t0, t1, t2, x3, y3;
 
@@ -338,8 +430,12 @@
             return 1;
         },
 
-        /* this+=Q - return 0 for add, 1 for double, -1 for O */
-        /* this+=Q */
+	/**
+         * Adds ECP2 instances
+         *
+         * param Q ECP2 instance
+         * @this {ECP2}
+         */		
         add: function(Q) {
             var b, t0, t1, t2, t3, t4, x3, y3, z3;
 
@@ -455,7 +551,12 @@
             return 0;
         },
 
-        /* this-=Q */
+	/**
+         * Subtracts ECP instance Q  from this
+         *
+         * @this {ECP2}
+         * @param Q ECP2 instance
+         */	
         sub: function(Q) {
             var D;
 			var NQ=new ECP2(); NQ.copy(Q);
@@ -464,7 +565,12 @@
             return D;
         },
 
-        /* P*=e */
+	/**
+         * Multiplies an ECP2 instance P by a BIG, side-channel resistant
+         *
+         * @this {ECP2}
+         * @param e BIG number multiplier
+         */		
         mul: function(e) {
             /* fixed size windows */
             var mt = new ctx.BIG(),
@@ -532,7 +638,11 @@
         }
     };
 
-    // set to group generator
+    /**
+      * Set group generator
+      *
+      * @this {ECP2}
+      */	
     ECP2.generator = function() {
         var G=new ECP2(),
             A = new ctx.BIG(0),
@@ -551,7 +661,12 @@
         return G;
     };
 
-    /* convert from byte array to point */
+    /**
+      * convert from byte array to point 
+      *
+      * @this {ECP2}
+      * @param b input byte array
+      */	    
     ECP2.fromBytes = function(b) {
         var t = [],
             ra, rb, i, rx, ry, P;
@@ -584,7 +699,12 @@
         return P;
     };
 
-    /* Calculate RHS of curve equation x^3+B */
+    /**
+      * Calculate RHS of curve equation x^3+B
+      *
+      * @this {ECP2}
+      * @param x x-value
+      */	    
     ECP2.RHS = function(x) {
         var r, c, b;
 
@@ -617,6 +737,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3 
+      *
+      * @this {ECP2}
+      */ 
     ECP2.mul4 = function(Q, u) {
         var W = new ECP2(),
             P = new ECP2(),
diff --git a/src/ecp4.js b/src/ecp4.js
index 9726b89..c11c520 100644
--- a/src/ecp4.js
+++ b/src/ecp4.js
@@ -22,7 +22,12 @@
 var ECP4 = function(ctx) {
     "use strict";
 
-    /* Constructor */
+    /**
+     * Creates an instance of ECP4
+     *
+     * @constructor
+     * @this {ECP4}
+    */    
     var ECP4 = function(input) {
         if (input instanceof ECP4) {
             // copy constructor
@@ -38,7 +43,13 @@
     };
 
     ECP4.prototype = {
-        /* Test this=O? */
+	
+        /**
+         * Tests for ECP4 point equal to infinity
+         *
+         * @this {ECP4}
+         * @param 1 if infinity, else returns 0
+         */	
         is_infinity: function() {
             this.x.reduce();
             this.y.reduce();
@@ -46,21 +57,34 @@
             return (this.x.iszilch() && this.z.iszilch());
         },
 
-        /* copy this=P */
+	/**
+         * Copy ECP4 point to another ECP4 point
+         *
+         * @this {ECP4}
+         * @param P ECP4 instance
+         */	
         copy: function(P) {
             this.x.copy(P.x);
             this.y.copy(P.y);
             this.z.copy(P.z);
         },
 
-        /* set this=O */
+	/**
+         * conditional move of Q to P dependant on d 
+         *
+         * @this {ECP4}
+         */	
         inf: function() {
             this.x.zero();
             this.y.one();
             this.z.zero();
         },
 
-        /* conditional move of Q to P dependant on d */
+	/**
+         * conditional move of Q to P dependant on d 
+         *
+         * @this {ECP4}
+         */	
         cmove: function(Q, d) {
             this.x.cmove(Q.x, d);
             this.y.cmove(Q.y, d);
@@ -68,7 +92,11 @@
 
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {ECP4}
+         */	
         select: function(W, b) {
             var MP = new ECP4(),
                 m = b >> 31,
@@ -90,7 +118,12 @@
             this.cmove(MP, (m & 1));
         },
 
-        /* Test P == Q */
+	/**
+         * Test P == Q 
+         *
+         * @this {ECP4}
+         * @param Q ECP4 instance 
+         */	
         equals: function(Q) {
             var a, b;
 
@@ -114,7 +147,11 @@
             return true;
         },
 
-        /* set this=-this */
+	/**
+         * set this=-this 
+         *
+         * @this {ECP4}
+         */	
         neg: function() {
             this.y.norm();
             this.y.neg();
@@ -122,7 +159,11 @@
             return;
         },
 
-        /* convert this to affine, from (x,y,z) to (x,y) */
+	/**
+         * convert this to affine, from (x,y,z) to (x,y) 
+         *
+         * @this {ECP4}
+         */	
         affine: function() {
             var one;
 
@@ -147,34 +188,59 @@
             this.z.copy(one);
         },
 
-        /* extract affine x as ctx.FP4 */
+	/**
+         * extract affine x as ctx.FP2 
+         *
+         * @this {ECP4}
+         */	
         getX: function() {
 			var W=new ECP4(); W.copy(this); W.affine();
             return W.x;
         },
 
-        /* extract affine y as ctx.FP4 */
+	/**
+         * extract affine y as ctx.FP2
+         *
+         * @this {ECP4}
+         */	
         getY: function() {
 			var W=new ECP4(); W.copy(this); W.affine();
             return W.y;
         },
 
-        /* extract projective x */
+	/**
+         * extract projective x
+         *
+         * @this {ECP4}
+         */	
         getx: function() {
             return this.x;
         },
 
-        /* extract projective y */
+	/**
+         * extract projective y
+         *
+         * @this {ECP4}
+         */	
         gety: function() {
             return this.y;
         },
 
-        /* extract projective z */
+	/**
+         * extract projective z
+         *
+         * @this {ECP4}
+         */	
         getz: function() {
             return this.z;
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte arrayextract projective x
+         *
+         * @this {ECP4}
+         * @param b byte array output
+         */	
         toBytes: function(b) {
             var t = [],
                 i;
@@ -216,7 +282,12 @@
             }
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string 
+         *
+         * @this {ECP4}
+         * @return hex string
+         */	
         toString: function() {
 			var W=new ECP4(); W.copy(this);
             if (W.is_infinity()) {
@@ -226,7 +297,13 @@
             return "(" + W.x.toString() + "," + W.y.toString() + ")";
         },
 
-        /* set this=(x,y) */
+	/**
+         * set this=(x,y)
+         *
+         * @this {ECP4}
+         * @param ix x-value
+         * @param iy y-value
+         */	
         setxy: function(ix, iy) {
             var rhs, y2;
 
@@ -246,7 +323,12 @@
 
         },
 
-        /* set this=(x,.) */
+	/**
+         * set this=(x,.) 
+         *
+         * @this {ECP4}
+         * @param ix x-value
+         */	
         setx: function(ix) {
             var rhs;
 
@@ -262,7 +344,11 @@
             }
         },
 
-        /* set this*=q, where q is Modulus, using Frobenius */
+	/**
+         * set this*=q, where q is Modulus, using Frobenius 
+         *
+         * @this {ECP4}
+         */	
         frob: function(F,n) {
             for (var i=0;i<n;i++) {
                 this.x.frob(F[2]);
@@ -276,7 +362,11 @@
             }
         },
 
-        /* this+=this */
+	/**
+         * this+=this 
+         *
+         * @this {ECP4}
+         */	
         dbl: function() {
             var iy, t0, t1, t2, x3, y3;
 
@@ -338,7 +428,12 @@
             return 1;
         },
 
-        /* this+=Q */
+	/**
+         * Adds ECP4 instances
+         *
+         * param Q ECP4 instance
+         * @this {ECP4}
+         */		
         add: function(Q) {
             var b, t0, t1, t2, t3, t4, x3, y3, z3;
 
@@ -441,7 +536,12 @@
             return 0;
         },
 
-        /* this-=Q */
+	/**
+         * Subtracts ECP instance Q  from this
+         *
+         * @this {ECP4}
+         * @param Q ECP4 instance
+         */	
         sub: function(Q) {
             var D;
 			var NQ=new ECP4(); NQ.copy(Q);
@@ -450,7 +550,12 @@
             return D;
         },
 
-        /* P*=e */
+	/**
+         * Multiplies an ECP4 instance P by a BIG, side-channel resistant
+         *
+         * @this {ECP4}
+         * @param e BIG number multiplier
+         */		
         mul: function(e) {
             /* fixed size windows */
             var mt = new ctx.BIG(),
@@ -518,7 +623,11 @@
         }
     };
 
-    // set to group generator
+    /**
+      * Set group generator
+      *
+      * @this {ECP4}
+      */	
     ECP4.generator = function() {
         var G=new ECP4(),
             A = new ctx.BIG(0),
@@ -550,7 +659,12 @@
         return G;
     };
 
-    /* convert from byte array to point */
+    /**
+      * convert from byte array to point 
+      *
+      * @this {ECP4}
+      * @param b input byte array
+      */	    
     ECP4.fromBytes = function(b) {
         var t = [],
             ra, rb, ra4, rb4, i, rx, ry, P;
@@ -606,7 +720,12 @@
         return P;
     };
 
-    /* Calculate RHS of curve equation x^3+B */
+    /**
+      * Calculate RHS of curve equation x^3+B
+      *
+      * @this {ECP4}
+      * @param x x-value
+      */	    
     ECP4.RHS = function(x) {
         var r, c, b;
 
@@ -636,6 +755,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... 
+      *
+      * @this {ECP4}
+      */ 
     ECP4.mul8 = function(Q, u) {
         var W = new ECP4(),
             P = new ECP4(),
diff --git a/src/ecp8.js b/src/ecp8.js
index 644f27f..b67cd43 100644
--- a/src/ecp8.js
+++ b/src/ecp8.js
@@ -22,7 +22,12 @@
 var ECP8 = function(ctx) {
     "use strict";
 
-    /* Constructor */
+    /**
+     * Creates an instance of ECP8
+     *
+     * @constructor
+     * @this {ECP8}
+    */    
     var ECP8 = function(input) {
         if (input instanceof ECP8) {
             // copy constructor
@@ -38,7 +43,13 @@
     };
 
     ECP8.prototype = {
-        /* Test this=O? */
+
+	/**
+         * Tests for ECP8 point equal to infinity
+         *
+         * @this {ECP8}
+         * @param 1 if infinity, else returns 0
+         */	
         is_infinity: function() {
 
             this.x.reduce();
@@ -47,28 +58,45 @@
             return (this.x.iszilch() && this.z.iszilch());
         },
 
-        /* copy this=P */
+	/**
+         * Copy ECP8 point to another ECP8 point
+         *
+         * @this {ECP8}
+         * @param P ECP8 instance
+         */	
         copy: function(P) {
             this.x.copy(P.x);
             this.y.copy(P.y);
             this.z.copy(P.z);
         },
 
-        /* set this=O */
+	/**
+         * Set ECP8 to point-at-infinity
+         *
+         * @this {ECP8}
+         */	
         inf: function() {
             this.x.zero();
             this.y.one();
             this.z.zero();
         },
 
-        /* conditional move of Q to P dependant on d */
+	/**
+         * conditional move of Q to P dependant on d 
+         *
+         * @this {ECP8}
+         */	
         cmove: function(Q, d) {
             this.x.cmove(Q.x, d);
             this.y.cmove(Q.y, d);
             this.z.cmove(Q.z, d);
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {ECP8}
+         */	
         select: function(W, b) {
             var MP = new ECP8(),
                 m = b >> 31,
@@ -90,7 +118,12 @@
             this.cmove(MP, (m & 1));
         },
 
-        /* Test P == Q */
+	/**
+         * Test P == Q 
+         *
+         * @this {ECP8}
+         * @param Q ECP8 instance 
+         */	
         equals: function(Q) {
             var a, b;
 
@@ -114,7 +147,11 @@
             return true;
         },
 
-        /* set this=-this */
+	/**
+         * set this=-this 
+         *
+         * @this {ECP8}
+         */	
         neg: function() {
             this.y.norm();
             this.y.neg();
@@ -122,7 +159,11 @@
             return;
         },
 
-        /* convert this to affine, from (x,y,z) to (x,y) */
+	/**
+         * convert this to affine, from (x,y,z) to (x,y) 
+         *
+         * @this {ECP8}
+         */	
         affine: function() {
             var one;
 
@@ -146,34 +187,59 @@
             this.z.copy(one);
         },
 
-        /* extract affine x as ctx.FP8 */
+	/**
+         * extract affine x as ctx.FP2 
+         *
+         * @this {ECP8}
+         */	
         getX: function() {
 			var W=new ECP8(); W.copy(this); W.affine();
             return W.x;
         },
 
-        /* extract affine y as ctx.FP8 */
+	/**
+         * extract affine y as ctx.FP2
+         *
+         * @this {ECP8}
+         */	
         getY: function() {
 			var W=new ECP8(); W.copy(this); W.affine();
             return W.y;
         },
 
-        /* extract projective x */
+	/**
+         * extract projective x
+         *
+         * @this {ECP8}
+         */	
         getx: function() {
             return this.x;
         },
 
-        /* extract projective y */
+	/**
+         * extract projective y
+         *
+         * @this {ECP8}
+         */	
         gety: function() {
             return this.y;
         },
 
-        /* extract projective z */
+	/**
+         * extract projective z
+         *
+         * @this {ECP8}
+         */	
         getz: function() {
             return this.z;
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte arrayextract projective x
+         *
+         * @this {ECP8}
+         * @param b byte array output
+         */	
         toBytes: function(b) {
             var t = [],
                 i;
@@ -248,7 +314,12 @@
             }
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string 
+         *
+         * @this {ECP8}
+         * @return hex string
+         */	
         toString: function() {
 			var W=new ECP8(); W.copy(this);
             if (W.is_infinity()) {
@@ -258,7 +329,13 @@
             return "(" + W.x.toString() + "," + W.y.toString() + ")";
         },
 
-        /* set this=(x,y) */
+	/**
+         * set this=(x,y)
+         *
+         * @this {ECP8}
+         * @param ix x-value
+         * @param iy y-value
+         */	
         setxy: function(ix, iy) {
             var rhs, y2;
 
@@ -277,7 +354,12 @@
             }
         },
 
-        /* set this=(x,.) */
+	/**
+         * set this=(x,.) 
+         *
+         * @this {ECP8}
+         * @param ix x-value
+         */	
         setx: function(ix) {
             var rhs;
 
@@ -293,7 +375,11 @@
             }
         },
 
-        /* set this*=q, where q is Modulus, using Frobenius */
+	/**
+         * set this*=q, where q is Modulus, using Frobenius 
+         *
+         * @this {ECP8}
+         */	
         frob: function(F,n) {
             for (var i=0;i<n;i++) {
                 this.x.frob(F[2]);
@@ -318,7 +404,11 @@
             }
         },
 
-        /* this+=this */
+	/**
+         * this+=this 
+         *
+         * @this {ECP8}
+         */	
         dbl: function() {
             var iy, t0, t1, t2, x3, y3;
 
@@ -380,7 +470,12 @@
             return 1;
         },
 
-        /* this+=Q */
+	/**
+         * Adds ECP8 instances
+         *
+         * param Q ECP8 instance
+         * @this {ECP8}
+         */		
         add: function(Q) {
             var b, t0, t1, t2, t3, t4, x3, y3, z3;
 
@@ -483,7 +578,12 @@
             return 0;
         },
 
-        /* this-=Q */
+	/**
+         * Subtracts ECP instance Q  from this
+         *
+         * @this {ECP8}
+         * @param Q ECP8 instance
+         */	
         sub: function(Q) {
             var D;
 			var NQ=new ECP8(); NQ.copy(Q);
@@ -492,7 +592,12 @@
             return D;
         },
 
-        /* P*=e */
+	/**
+         * Multiplies an ECP8 instance P by a BIG, side-channel resistant
+         *
+         * @this {ECP8}
+         * @param e BIG number multiplier
+         */		
         mul: function(e) {
             /* fixed size windows */
             var mt = new ctx.BIG(),
@@ -560,7 +665,11 @@
         }
     };
 
-    // set to group generator
+    /**
+      * Set group generator
+      *
+      * @this {ECP8}
+      */	
     ECP8.generator = function() {
         var G=new ECP8(),
             A = new ctx.BIG(0),
@@ -618,7 +727,12 @@
         return G;
     };
 
-    /* convert from byte array to point */
+    /**
+      * convert from byte array to point 
+      *
+      * @this {ECP8}
+      * @param b input byte array
+      */	    
     ECP8.fromBytes = function(b) {
         var t = [],
             ra, rb, ra4, rb4, ra8, rb8, i, rx, ry, P;
@@ -722,7 +836,12 @@
         return P;
     };
 
-    /* Calculate RHS of curve equation x^3+B */
+    /**
+      * Calculate RHS of curve equation x^3+B
+      *
+      * @this {ECP8}
+      * @param x x-value
+      */	    
     ECP8.RHS = function(x) {
         var r, c, b;
 
@@ -752,6 +871,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * Calculate P=u0.Q0+u1*Q1+u2*Q2+u3*Q3... 
+      *
+      * @this {ECP8}
+      */     
     ECP8.mul16 = function(Q, u) {
         var W = new ECP8(),
             P = new ECP8(),
diff --git a/src/ff.js b/src/ff.js
index 8bcd3c4..23b7e8c 100644
--- a/src/ff.js
+++ b/src/ff.js
@@ -22,7 +22,12 @@
 var FF = function(ctx) {
     "use strict";
 
-    /* General purpose Constructor */
+    /**
+      * Creates an instance of FF.
+      *
+      * @constructor
+      * @this {FF}
+      */
     var FF = function(n) {
         this.v = new Array(n);
         this.length = n;
@@ -58,32 +63,59 @@
             return this.length;
         },
 
-        /* set to integer */
+	/**
+         * set to integer 
+         *
+         * @this {FF}
+         * @param m  Integer value to be set to
+         */
         set: function(m) {
             this.zero();
             this.v[0].set(0, (m & ctx.BIG.BMASK));
             this.v[0].set(1, (m >> ctx.BIG.BASEBITS));
         },
-        /* copy from FF b */
+
+	/**
+         * copy from FF b 
+         *
+         * @this {FF}
+         * @param b  FF element to copy from
+         */
         copy: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].copy(b.v[i]);
             }
         },
-        /* copy from FF b */
+	
+	/**
+         * copy from FF b 
+         *
+         * @this {FF}
+         * @param b  FF element to copy from
+         */
         rcopy: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].rcopy(b[i]);
             }
         },
-        /* x=y<<n */
+	
+	/**
+         * x=y<<n 
+         *
+         * @this {FF}
+         */
         dsucopy: function(b) {
             for (var i = 0; i < b.length; i++) {
                 this.v[b.length + i].copy(b.v[i]);
                 this.v[i].zero();
             }
         },
-        /* x=y */
+	
+	/**
+         * x=y
+         *
+         * @this {FF}
+         */
         dscopy: function(b) {
             for (var i = 0; i < b.length; i++) {
                 this.v[i].copy(b.v[i]);
@@ -91,19 +123,29 @@
             }
         },
 
-        /* x=y>>n */
+	/**
+         * x=y>>n 
+         *
+         * @this {FF}
+         */
         sducopy: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].copy(b.v[this.length + i]);
             }
         },
+	
         one: function() {
             this.v[0].one();
             for (var i = 1; i < this.length; i++) {
                 this.v[i].zero();
             }
         },
-        /* test equals 0 */
+	
+	/**
+         * test equals 0
+         *
+         * @this {FF}
+         */
         iszilch: function() {
             for (var i = 0; i < this.length; i++) {
                 if (!this.v[i].iszilch()) {
@@ -113,7 +155,12 @@
 
             return true;
         },
-        /* shift right by BIGBITS-bit words */
+	
+	/**
+         * shift right by BIGBITS-bit words
+         *
+         * @this {FF}
+         */
         shrw: function(n) {
             for (var i = 0; i < n; i++) {
                 this.v[i].copy(this.v[i + n]);
@@ -121,14 +168,23 @@
             }
         },
 
-        /* shift left by BIGBITS-bit words */
+	/**
+         * shift left by BIGBITS-bit words
+         *
+         * @this {FF}
+         */
         shlw: function(n) {
             for (var i = 0; i < n; i++) {
                 this.v[n + i].copy(this.v[i]);
                 this.v[i].zero();
             }
         },
-        /* extract last bit */
+	
+	/**
+         * extract last bit
+         *
+         * @this {FF}
+         */
         parity: function() {
             return this.v[0].parity();
         },
@@ -137,7 +193,11 @@
             return this.v[0].lastbits(m);
         },
 
-        /* recursive add */
+	/**
+         * recursive add
+         *
+         * @this {FF}
+         */
         radd: function(vp, x, xp, y, yp, n) {
             for (var i = 0; i < n; i++) {
                 this.v[vp + i].copy(x.v[xp + i]);
@@ -145,14 +205,22 @@
             }
         },
 
-        /* recursive inc */
+	/**
+         * recursive inc
+         *
+         * @this {FF}
+         */
         rinc: function(vp, y, yp, n) {
             for (var i = 0; i < n; i++) {
                 this.v[vp + i].add(y.v[yp + i]);
             }
         },
 
-        /* recursive sub */
+	/**
+         * recursive sub
+         *
+         * @this {FF}
+         */
         rsub: function(vp, x, xp, y, yp, n) {
             for (var i = 0; i < n; i++) {
                 this.v[vp + i].copy(x.v[xp + i]);
@@ -160,35 +228,55 @@
             }
         },
 
-        /* recursive dec */
+	/**
+         * recursive dec
+         *
+         * @this {FF}
+         */
         rdec: function(vp, y, yp, n) {
             for (var i = 0; i < n; i++) {
                 this.v[vp + i].sub(y.v[yp + i]);
             }
         },
 
-        /* simple add */
+	/**
+         * simple add
+         *
+         * @this {FF}
+         */
         add: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].add(b.v[i]);
             }
         },
 
-        /* simple sub */
+	/**
+         * simple sub
+         *
+         * @this {FF}
+         */
         sub: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].sub(b.v[i]);
             }
         },
 
-        /* reverse sub */
+	/**
+         * reverse sub 
+         *
+         * @this {FF}
+         */
         revsub: function(b) {
             for (var i = 0; i < this.length; i++) {
                 this.v[i].rsub(b.v[i]);
             }
         },
 
-        /* increment/decrement by a small integer */
+	/**
+         * increment/decrement by a small integer
+         *
+         * @this {FF}
+         */
         inc: function(m) {
             this.v[0].inc(m);
             this.norm();
@@ -199,7 +287,11 @@
             this.norm();
         },
 
-        /* normalise - but hold any overflow in top part unless n<0 */
+	/**
+         * normalise - but hold any overflow in top part unless n<0 
+         *
+         * @this {FF}
+         */
         rnorm: function(vp, n) {
             var trunc = false,
                 i, carry;
@@ -227,7 +319,11 @@
             this.rnorm(0, this.length);
         },
 
-        /* shift left by one bit */
+	/**
+         * shift left by one bit 
+         *
+         * @this {FF}
+         */
         shl: function() {
             var delay_carry = 0,
                 i, carry;
@@ -243,7 +339,11 @@
             this.v[this.length - 1].inc(delay_carry);
         },
 
-        /* shift right by one bit */
+	/**
+         * shift right by one bit
+         *
+         * @this {FF}
+         */
         shr: function() {
             var i, carry;
 
@@ -255,7 +355,11 @@
             this.v[0].fshr(1);
         },
 
-        /* Convert to Hex String */
+	/**
+         * Convert to Hex String 
+         *
+         * @this {FF}
+         */
         toString: function() {
             var s = "",
                 i;
@@ -268,7 +372,12 @@
 
             return s;
         },
-        /* Convert FFs to/from byte arrays */
+	
+	/**
+         * Convert FFs to/from byte arrays
+         *
+         * @this {FF}
+         */
         toBytes: function(b) {
             var i;
 
@@ -277,7 +386,11 @@
             }
         },
 
-        /* z=x*y, t is workspace */
+	/**
+         * z=x*y, t is workspace
+         *
+         * @this {FF}
+         */
         karmul: function(vp, x, xp, y, yp, t, tp, n) {
             var nd2, d;
 
@@ -368,7 +481,11 @@
             this.rnorm(nd2, n);
         },
 
-        /* return low part of product this*y */
+	/**
+         * return low part of product this*y
+         *
+         * @this {FF}
+         */
         lmul: function(y) {
             var n = this.length,
                 t = new FF(2 * n),
@@ -378,7 +495,11 @@
             this.karmul_lower(0, x, 0, y, 0, t, 0, n);
         },
 
-        /* Set b=b mod c */
+	/**
+         * Set b=b mod c
+         *
+         * @this {FF}
+         */
         mod: function(c) {
             var k = 0;
 
@@ -404,7 +525,14 @@
             }
         },
 
-        /* return This mod modulus, N is modulus, ND is Montgomery Constant */
+	/**
+         * return this mod modulus
+         *
+         * @this {FF}
+         * @param N Mmodulus
+         * @param ND Montgomery Constant
+         * @return this mod N
+         */
         reduce: function(N, ND) { /* fast karatsuba Montgomery reduction */
             var n = N.length,
                 t = new FF(2 * n),
@@ -426,6 +554,14 @@
         /* Set r=this mod b */
         /* this is of length - 2*n */
         /* r,b is of length - n */
+	
+	/**
+         * Reduces a double-length FF with respect to a given modulus
+         *
+         * @this {FF}
+         * @param b Mmodulus
+         * @return this mod N
+         */	
         dmod: function(b) {
             var n = b.length,
                 m = new FF(2 * n),
@@ -460,7 +596,11 @@
             return r;
         },
 
-        /* Set return=1/this mod p. Binary method - a<p on entry */
+	/**
+         * Set return=1/this mod p. Binary method - a<p on entry
+         *
+         * @this {FF}
+         */	
         invmodp: function(p) {
             var n = p.length,
                 u = new FF(n),
@@ -532,7 +672,11 @@
             }
         },
 
-        /* nresidue mod m */
+	/**
+         * nresidue mod m 
+         *
+         * @this {FF}
+         */	
         nres: function(m) {
             var n = m.length,
                 d;
@@ -572,7 +716,11 @@
             }
         },
 
-        /* U=1/a mod 2^m - Arazi & Qi */
+        /** 
+         * U=1/a mod 2^m - Arazi & Qi
+         *
+         * @this {FF}
+         */	
         invmod2m: function() {
             var n = this.length,
                 b = new FF(n),
@@ -627,7 +775,11 @@
             }
         },
 
-        /* generate random x */
+        /** 
+         * generate random x 
+         *
+         * @this {FF}
+         */	
         randomnum: function(p, rng) {
             var n = this.length,
                 d = new FF(2 * n),
@@ -640,7 +792,11 @@
             this.copy(d.dmod(p));
         },
 
-        /* this*=y mod p */
+        /** 
+         * this*=y mod p
+         *
+         * @this {FF}
+         */	
         modmul: function(y, p, nd) {
             var ex = this.P_EXCESS(),
                 ey = y.P_EXCESS(),
@@ -660,7 +816,11 @@
             }
         },
 
-        /* this*=y mod p */
+        /** 
+         * this*=y mod p
+         *
+         * @this {FF}
+         */	
         modsqr: function(p, nd) {
             var ex = this.P_EXCESS(),
                 n, d;
@@ -679,7 +839,13 @@
             }
         },
 
-        /* this=this^e mod p using side-channel resistant Montgomery Ladder, for large e */
+        /** 
+         * this=this^e mod p using side-channel resistant Montgomery Ladder, for large e
+         *
+         * @this {FF}
+         * @param e exponent
+         * @param p modulus
+         */		
         skpow: function(e, p) {
             var n = p.length,
                 R0 = new FF(n),
@@ -710,7 +876,13 @@
             this.redc(p, ND);
         },
 
-        /* this =this^e mod p using side-channel resistant Montgomery Ladder, for short e */
+        /** 
+         * this=this^e mod p using side-channel resistant Montgomery Ladder, for short e
+         *
+         * @this {FF}
+         * @param e exponent
+         * @param p modulus
+         */		
         skspow: function(e, p) {
             var n = p.length,
                 R0 = new FF(n),
@@ -739,7 +911,13 @@
             this.redc(p, ND);
         },
 
-        /* raise to an integer power - right-to-left method */
+        /** 
+         * raise to an integer power - right-to-left method
+         *
+         * @this {FF}
+         * @param e exponent
+         * @param p modulus
+         */		
         power: function(e, p) {
             var n = p.length,
                 f = true,
@@ -773,7 +951,13 @@
             this.redc(p, ND);
         },
 
-        /* this=this^e mod p, faster but not side channel resistant */
+        /** 
+         * this=this^e mod p, faster but not side channel resistant
+         *
+         * @this {FF}
+         * @param e exponent
+         * @param p modulus
+         */		
         pow: function(e, p) {
             var n = p.length,
                 w = new FF(n),
@@ -796,7 +980,15 @@
             this.redc(p, ND);
         },
 
-        /* double exponentiation r=x^e.y^f mod p */
+        /** 
+         * double exponentiation r=x^e.y^f mod p 
+         *
+         * @this {FF}
+         * @param e exponent
+         * @param y FF instance
+         * @param f exponent
+         * @param p modulus
+         */		
         pow2: function(e, y, f, p) {
             var n = p.length,
                 xn = new FF(n),
@@ -834,7 +1026,13 @@
             this.redc(p, ND);
         },
 
-        /* quick and dirty check for common factor with n */
+        /** 
+         * Test if an FF has factor in common with integer s
+         *
+         * @this {FF}
+         * @param s integerexponent
+         * @return true or false
+         */		
         cfactor: function(s) {
             var n = this.length,
                 x = new FF(n),
@@ -864,7 +1062,14 @@
         }
     };
 
-    /* compare x and y - must be normalised, and of same length */
+    /** 
+      * compare a and b - must be normalised, and of same length
+      *
+      * @this {FF}
+      * @param a FF number
+      * @param b FF number
+      * @return zero of error codetrue or false
+      */		
     FF.comp = function(a, b) {
         var i, j;
 
@@ -886,7 +1091,11 @@
         }
     };
 
-    /* in-place swapping using xor - side channel resistant - lengths must be the same */
+    /** 
+      * in-place swapping using xor - side channel resistant - lengths must be the same
+      *
+      * @this {FF}
+      */		
     FF.cswap = function(a, b, d) {
         var i;
 
@@ -895,7 +1104,11 @@
         }
     };
 
-    /* z=x*y. Assumes x and y are of same length. */
+    /** 
+      * z=x*y. Assumes x and y are of same length.
+      *
+      * @this {FF}
+      */		
     FF.mul = function(x, y) {
         var n = x.length,
             z = new FF(2 * n),
@@ -906,7 +1119,11 @@
         return z;
     };
 
-    /* z=x^2 */
+    /** 
+      * z=x^2
+      *
+      * @this {FF}
+      */		
     FF.sqr = function(x) {
         var n = x.length,
             z = new FF(2 * n),
@@ -932,7 +1149,13 @@
         return y;
     };
 
-    /* Miller-Rabin test for primality. Slow. */
+    /** 
+      * Miller-Rabin test for primality.
+      *
+      * @this {FF}
+      * @param p FF instance to be tested
+      * @param rmg an instance of a Cryptographically Secure Random Number Generator
+      */		
     FF.prime = function(p, rng) {
         var n = p.length,
             s = 0,
diff --git a/src/fp.js b/src/fp.js
index ebb0d74..2c37850 100644
--- a/src/fp.js
+++ b/src/fp.js
@@ -23,7 +23,13 @@
 var FP = function(ctx) {
     "use strict";
 
-    /* General purpose Constructor */
+    /**
+      * Creates an instance of FP.
+      *
+      * @constructor
+      * @this {FP}
+      * @param x FP / BIG instance
+      */
     var FP = function(x) {
         if (x instanceof FP) {
             this.f = new ctx.BIG(x.f);
@@ -57,31 +63,57 @@
     FP.TMASK = (1 << FP.TBITS) - 1;
 
     FP.prototype = {
-        /* set this=0 */
+	
+	/**
+         * Set FP to zero
+         *
+         * @this {FP}
+         */
         zero: function() {
             this.XES = 1;
             this.f.zero();
         },
 
-        /* copy from a ctx.BIG in ROM */
+	/**
+         * copy from a ctx.BIG in ROM 
+         *
+         * @this {FP}
+         * @param x FP instance to be copied
+         */
         rcopy: function(y) {
             this.f.rcopy(y);
             this.nres();
         },
 
-        /* copy from another ctx.BIG */
+	/**
+         * copy from another ctx.BIG 
+         *
+         * @this {FP}
+         * @param x FP instance to be copied
+         */
         bcopy: function(y) {
             this.f.copy(y);
             this.nres();
         },
 
-        /* copy from another FP */
+	/**
+         * Copy FP to another FP
+         *
+         * @this {FP}
+         * @param x FP instance to be copied
+         */
         copy: function(y) {
             this.XES = y.XES;
             this.f.copy(y.f);
         },
 
-        /* conditional swap of a and b depending on d */
+	/**
+         * Conditional constant time swap of two FP numbers
+         *
+         * @this {BIG}
+         * @parameter b FP number 
+         * @parameter d Integer
+         */		
         cswap: function(b, d) {
             this.f.cswap(b.f, d);
             var t, c = d;
@@ -91,7 +123,13 @@
             b.XES ^= t;
         },
 
-        /* conditional copy of b to a depending on d */
+	/**
+         * Conditional copy of FP number
+         *
+         * @this {FP}
+         * @param g FP instance
+         * @param d copy depends on this value
+         */
         cmove: function(b, d) {
             var c = d;
 
@@ -101,7 +139,11 @@
             this.XES ^= (this.XES ^ b.XES) & c;
         },
 
-        /* convert to Montgomery n-residue form */
+	/**
+         * Converts from BIG integer to residue form mod Modulus
+         *
+         * @this {FP}
+         */
         nres: function() {
             var r, d;
 
@@ -119,7 +161,11 @@
             return this;
         },
 
-        /* convert back to regular form */
+	/**
+         * Converts from residue form back to BIG integer form
+         *
+         * @this {FP}
+         */
         redc: function() {
             var r = new ctx.BIG(0),
                 d, w;
@@ -136,20 +182,32 @@
             return r;
         },
 
-        /* convert this to string */
+	/**
+         * convert to hex string
+         *
+         * @this {FP}
+         */
         toString: function() {
             var s = this.redc().toString();
             return s;
         },
 
-        /* test this=0 */
+	/**
+         * Tests for FP equal to zero
+         *
+         * @this {FP}
+         */
         iszilch: function() {
 			var c=new FP(0); c.copy(this);
             c.reduce();
             return c.f.iszilch();
         },
 
-        /* reduce this mod Modulus */
+	/**
+         * Reduces all components of possibly unreduced FP mod Modulus
+         *
+         * @this {FP}
+         */
         reduce: function() {
             var q,carry,sr,sb,m = new ctx.BIG(0);
             m.rcopy(ctx.ROM_FIELD.Modulus);
@@ -182,18 +240,31 @@
             this.XES = 1;
         },
 
-        /* set this=1 */
+	/**
+         * Set FP to unity
+         *
+         * @this {FP}
+         */
         one: function() {
             this.f.one();
             this.nres();
         },
 
-        /* normalise this */
+	/**
+         * Normalises the components of an FP
+         *
+         * @this {FP}
+         */
         norm: function() {
             return this.f.norm();
         },
 
-        /* this*=b mod Modulus */
+	/**
+         * Fast Modular multiplication of two FPs, mod Modulus
+         *
+         * @this {FP}
+         * @param b FP number, the multiplier
+         */
         mul: function(b) {
             var d;
 
@@ -208,7 +279,12 @@
             return this;
         },
 
-        /* this*=c mod Modulus where c is an int */
+	/**
+         * Multiplication of an FP by a small integer
+         *
+         * @this {FP}
+         * @param s integer
+         */
         imul: function(c) {
             var s = false,
                 d, n;
@@ -239,7 +315,11 @@
             return this;
         },
 
-        /* this*=this mod Modulus */
+	/**
+         * Fast Squaring of an FP
+         *
+         * @this {FP}
+         */
         sqr: function() {
             var d, t;
 
@@ -266,7 +346,13 @@
 
             return this;
         },
-        /* this=-this mod Modulus */
+	
+	/**
+         * negate this
+         *
+         * @this {FP}
+         * @param x FP instance to be set to one
+         */
         neg: function() {
             var m = new ctx.BIG(0),
                 sb;
@@ -286,7 +372,12 @@
             return this;
         },
 
-        /* this-=b */
+	/**
+         * subtraction of two FPs
+         *
+         * @this {FP}
+         * @param x FP instance
+         */
         sub: function(b) {
             var n = new FP(0);
 
@@ -306,7 +397,11 @@
             this.add(n);
         },
 
-        /* this/=2 mod Modulus */
+	/**
+         * Divide an FP by 2
+         *
+         * @this {FP}
+         */
         div2: function() {
             var p;
 
@@ -325,8 +420,14 @@
         },
 
 // return this^(p-3)/4 or this^(p-5)/8
-// See https://eprint.iacr.org/2018/1038
-		fpow: function() {
+	// See https://eprint.iacr.org/2018/1038
+
+	/**
+         * return this^(p-3)/4 or this^(p-5)/8
+         *
+         * @this {FP}
+         */	
+	fpow: function() {
 			var i,j,k,bw,w,c,nw,lo,m,n;
 			var xp=[];
 			var ac=[1,2,3,6,12,15,30,60,120,240,255];
@@ -427,7 +528,11 @@
 			return r;
 		},
 
-        /* this=1/this mod Modulus */
+	/**
+         * Inverting an FP
+         *
+         * @this {FP}
+         */
         inverse: function() {
 
 			if (FP.MODTYPE == FP.PSEUDO_MERSENNE || FP.MODTYPE == FP.GENERALISED_MERSENNE)
@@ -454,7 +559,12 @@
 			}
         },
 
-        /* return TRUE if this==a */
+	/**
+         * Tests for equality of two FP instances
+         *
+         * @this {FP}
+         * @param x FP instance to compare
+         */
         equals: function(a) {
 			var ft=new FP(0); ft.copy(this);
 			var sd=new FP(0); sd.copy(a);
@@ -468,7 +578,12 @@
             return false;
         },
 
-        /* return this^e mod Modulus */
+	/**
+         * Raises an FP to the power of a BIG
+         *
+         * @this {FP}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var i,w=[],
                 tb=[],
@@ -503,7 +618,11 @@
             return r;
         },
 
-        /* return jacobi symbol (this/Modulus) */
+	/**
+         * return jacobi symbol (this/Modulus)
+         *
+         * @this {FP}
+         */
         jacobi: function() {
             var p = new ctx.BIG(0),
                 w = this.redc();
@@ -513,7 +632,11 @@
             return w.jacobi(p);
         },
 
-        /* return sqrt(this) mod Modulus */
+	/**
+         * Fast Modular square root of a an FP, mod Modulus
+         *
+         * @this {FP}
+         */
         sqrt: function() {
             var i, v, r;
 
@@ -590,7 +713,11 @@
 		return Math.floor(num/(den+1))
 	};
 
-    /* reduce a ctx.DBIG to a ctx.BIG using a "special" modulus */
+    /**
+      * reduce a ctx.DBIG to a ctx.BIG using a "special" modulus 
+      *
+      * @this {FP}
+      */    
     FP.mod = function(d) {
         var b = new ctx.BIG(0),
             i, t, v, tw, tt, lo, carry, m, dd;
diff --git a/src/fp12.js b/src/fp12.js
index aa29a39..5dfbee1 100644
--- a/src/fp12.js
+++ b/src/fp12.js
@@ -24,7 +24,12 @@
 var FP12 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP12.
+      *
+      * @constructor
+      * @this {FP12}
+      */
     var FP12 = function(d, e, f) {
         if (d instanceof FP12) {
             // ignore e, d, which are assumed be undefined in this case
@@ -55,33 +60,56 @@
     };
 
     FP12.prototype = {
-        /* reduce all components of this mod Modulus */
+	
+	/**
+         * Reduces all components of possibly unreduced FP12 mod Modulus
+         *
+         * @this {FP12}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
             this.c.reduce();
         },
 
-        /* normalize all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP12
+         *
+         * @this {FP12}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
             this.c.norm();
         },
 
-        /* test x==0 ? */
+	/**
+         * Tests for FP12 equal to zero
+         *
+         * @this {FP12}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
         },
 
-        /* test x==1 ? */
+	/**
+         * Tests for FP12 equal to unity
+         *
+         * @this {FP12}
+         */
         isunity: function() {
             var one = new ctx.FP4(1);
             return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
         },
 
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP12 number
+         *
+         * @this {FP12}
+         * @param g FP12 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
@@ -91,8 +119,12 @@
         },
 
 
-        /* Constant time select from pre-computed table */
-        select: function(g, b) {
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {FP12}
+         */
+         select: function(g, b) {
             var invf = new FP12(0),
                 m, babs;
 
@@ -122,27 +154,49 @@
 			return this.stype;
 		},
 
-        /* extract a from this */
+	/**
+         * extract a from this
+         *
+         * @this {FP12}
+         */
         geta: function() {
             return this.a;
         },
 
-        /* extract b */
+	/**
+         * extract b from this
+         *
+         * @this {FP12}
+         */
         getb: function() {
             return this.b;
         },
 
-        /* extract c */
+	/**
+         * extract c from this
+         *
+         * @this {FP12}
+         */
         getc: function() {
             return this.c;
         },
 
-        /* return 1 if x==y, else 0 */
+	/**
+         * Tests for equality of two FP12s
+         *
+         * @this {FP12}
+         * @param x FP12 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP12 to another FP12
+         *
+         * @this {FP12}
+         * @param x FP12 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
@@ -150,7 +204,12 @@
 			this.stype=x.stype;
         },
 
-        /* set this=1 */
+	/**
+         * Set FP12 to unity
+         *
+         * @this {FP12}
+         * @param x FP12 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
@@ -158,7 +217,11 @@
 			this.stype=ctx.FP.ONE;
         },
 
-        /* set this=0 */
+	/**
+         * Set FP12 to zero
+         *
+         * @this {FP12}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
@@ -166,30 +229,50 @@
 			this.stype=ctx.FP.ZERO;
         },
 
-        /* this=conj(this) */
+	/**
+         * Conjugation of FP12
+         *
+         * @this {FP12}
+         */
         conj: function() {
             this.a.conj();
             this.b.nconj();
             this.c.conj();
         },
 
-        /* set this from 3 FP4s */
+	/**
+         * Set FP12 from three FP4 values
+         *
+         * @this {FP12}
+         * @param d FP4 instance
+         * @param e FP4 instance
+         * @param f FP4 instance
+         */
         set: function(d, e, f) {
             this.a.copy(d);
             this.b.copy(e);
             this.c.copy(f);
-			this.stype=ctx.FP.DENSE;
+	    this.stype=ctx.FP.DENSE;
         },
 
-        /* set this from one ctx.FP4 */
+	/**
+         * Set FP12 from one FP4 value
+         *
+         * @this {FP12}
+         * @param d FP4 instance
+         */
         seta: function(d) {
             this.a.copy(d);
             this.b.zero();
             this.c.zero();
-			this.stype=ctx.FP.SPARSER
+	    this.stype=ctx.FP.SPARSER
         },
 
-        /* Granger-Scott Unitary Squaring */
+	/**
+         * Fast Squaring of an FP12 in "unitary" form
+         *
+         * @this {FP12}
+         */
         usqr: function() {
             var A = new ctx.FP4(this.a), 
                 B = new ctx.FP4(this.c), 
@@ -228,7 +311,11 @@
             this.reduce();
         },
 
-        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	/**
+         * Fast Squaring of an FP12
+         *
+         * @this {FP12}
+         */
         sqr: function() {
 			if (this.stype==ctx.FP.ONE)
 				return;
@@ -270,7 +357,12 @@
             this.norm();
         },
 
-        /* FP12 full multiplication this=this*y */
+	/**
+         * Full unconditional Multiplication of two FP12s
+         *
+         * @this {FP12}
+         * @param y FP12 instance, the multiplier
+         */
         mul: function(y) {
             var z0 = new ctx.FP4(this.a), 
                 z1 = new ctx.FP4(0),
@@ -343,8 +435,15 @@
 
 /* FP12 multiplication w=w*y */
 /* catering for special case that arises from special form of ATE pairing line function */
-/* w and y are both sparser line functions - cost = 6m */ 
-		smul: function(y) {
+	/* w and y are both sparser line functions - cost = 6m */
+
+	/**
+         * Fast multiplication of two sparse FP12s that arises from ATE pairing line functions
+         *
+         * @this {FP12}
+         * @param y FP12 instance, the multiplier
+         */
+	smul: function(y) {
 			if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
 			{	
 				var w1=new ctx.FP2(this.a.geta());
@@ -454,8 +553,15 @@
 
 /* FP12 full multiplication w=w*y */
 /* Supports sparse multiplicands */
-/* Usually w is denser than y */
-		ssmul: function(y) {
+	/* Usually w is denser than y */
+
+	/**
+         * Fast multiplication of what may be sparse multiplicands
+         *
+         * @this {FP12}
+         * @param y FP12 instance, the multiplier
+         */
+	ssmul: function(y) {
 			if (this.stype==ctx.FP.ONE)
 			{
 				this.copy(y);
@@ -649,7 +755,11 @@
 			this.norm();
 		},
 
-        /* this=1/this */
+	/**
+         * Inverting an FP12
+         *
+         * @this {FP12}
+         */
         inverse: function() {
             var f0 = new ctx.FP4(this.a), 
                 f1 = new ctx.FP4(this.b), 
@@ -696,7 +806,12 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* this=this^p, where p=Modulus, using Frobenius */
+	/**
+         * Raises an FP12 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP12}
+         * @param f Modulus
+         */
         frob: function(f) {
             var f2 = new ctx.FP2(f),
                 f3 = new ctx.FP2(f);
@@ -713,7 +828,11 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* trace function */
+	/**
+         * Calculate the trace of an FP12
+         *
+         * @this {FP12}
+         */
         trace: function() {
             var t = new ctx.FP4(0);
 
@@ -724,12 +843,21 @@
             return t;
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string
+         *
+         * @this {FP12}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte array
+         *
+         * @this {FP12}
+         * @param w Byte array
+         */
         toBytes: function(w) {
             var t = [],
                 i;
@@ -786,7 +914,12 @@
             }
         },
 
-        /* set this=this^e */
+	/**
+         * Raises an FP12 to the power of a BIG
+         *
+         * @this {FP12}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var e1, e3, w, nb, i, bt, sf;
 			e1 = new ctx.BIG(e);
@@ -818,7 +951,13 @@
             return w;
         },
 
-        /* constant time powering by small integer of max length bts */
+	/**
+         * Raises an FP12 instance x to a small integer power, side-channel resistant
+         *
+         * @this {FP12}
+         * @param e small integer exponent
+         * @param bts maximum number of bits in exponent
+         */
         pinpow: function(e, bts) {
             var R = [],
                 i, b;
@@ -835,7 +974,13 @@
             this.copy(R[0]);
         },
 
-        /* Faster compressed powering for unitary elements */
+	/**
+         * Raises an FP12 instance to a BIG power, compressed to FP4
+         *
+         * @this {FP12}
+         * @param e BIG exponent
+         * @param r BIG group order
+         */
         compow: function(e, r) {
             var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
 
@@ -882,7 +1027,12 @@
         }
     };
 
-    /* convert from byte array to FP12 */
+    /**
+      * convert from byte array to FP12 
+      *
+      * @this {FP12}
+      * @param w Byte array
+      */    
     FP12.fromBytes = function(w) {
         var t = [],
             i, a, b, c, d, e, f, g, r;
@@ -959,7 +1109,11 @@
     };
 
 
-    /* return 1 if b==c, no branching */
+    /**
+      * return 1 if b==c, no branching 
+      *
+      * @this {FP12}
+      */    
     FP12.teq = function(b, c) {
         var x = b ^ c;
         x -= 1; // if x=0, x now -1
@@ -970,6 +1124,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * p=q0^u0.q1^u1.q2^u2.q3^u3 
+      *
+      * @this {FP12}
+      */    
     FP12.pow4 = function(q, u) {
         var g = [],
             r = new FP12(0),
diff --git a/src/fp16.js b/src/fp16.js
index 14d10e8..0627f73 100644
--- a/src/fp16.js
+++ b/src/fp16.js
@@ -24,7 +24,12 @@
 var FP16 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP16.
+      *
+      * @constructor
+      * @this {FP16}
+      */
     var FP16 = function(c, d) {
         if (c instanceof FP16) {
             this.a = new ctx.FP8(c.a);
@@ -36,90 +41,164 @@
     };
 
     FP16.prototype = {
-        /* reduce all components of this mod Modulus */
+	
+	/**
+         * Reduces all components of possibly unreduced FP16 mod Modulus
+         *
+         * @this {FP16}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
         },
 
-        /* normalise all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP16
+         *
+         * @this {FP16}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
         },
 
-        /* test this==0 ? */
+	/**
+         * Tests for FP16 equal to zero
+         *
+         * @this {FP16}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch());
         },
 
-        /* test this==1 ? */
+	/**
+         * Tests for FP16 equal to unity
+         *
+         * @this {FP16}
+         */
         isunity: function() {
             var one = new ctx.FP8(1);
             return (this.a.equals(one) && this.b.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP16 number
+         *
+         * @this {FP16}
+         * @param g FP16 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
         },
 
-        /* test is w real? That is in a+ib test b is zero */
+	/**
+         * test is w real? That is in a+ib test b is zero 
+         *
+         * @this {FP16}
+         */
         isreal: function() {
             return this.b.iszilch();
         },
 
-        /* extract real part a */
+	/**
+         * extract real part a
+         *
+         * @this {FP16}
+         */
         real: function() {
             return this.a;
         },
 
+	/**
+         * extract a from this
+         *
+         * @this {FP16}
+         */	
         geta: function() {
             return this.a;
         },
 
-        /* extract imaginary part b */
+	/**
+         * extract b from this
+         *
+         * @this {FP16}
+         */
         getb: function() {
             return this.b;
         },
 
-        /* test this=x? */
+	/**
+         * Tests for equality of two FP16s
+         *
+         * @this {FP16}
+         * @param x FP16 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP16 to another FP16
+         *
+         * @this {FP16}
+         * @param x FP16 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
         },
 
-        /* this=0 */
+	/**
+         * Set FP16 to zero
+         *
+         * @this {FP16}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
         },
 
-        /* this=1 */
+	/**
+         * Set FP16 to unity
+         *
+         * @this {FP16}
+         * @param x FP16 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
         },
 
-        /* set from two FP8s */
+	/**
+         * Set FP16 from two FP8 values
+         *
+         * @this {FP16}
+         * @param c FP8 instance
+         * @param d FP8 instance
+         */
         set: function(c, d) {
             this.a.copy(c);
             this.b.copy(d);
         },
 
-        /* set a */
+	/**
+         * Set FP16 from one FP8 value
+         *
+         * @this {FP16}
+         * @param c FP8 instance
+         */
         seta: function(c) {
             this.a.copy(c);
             this.b.zero();
         },
 
-        /* this=-this */
+	/**
+         * this=-this
+         *
+         * @this {FP16}
+         */
         neg: function() {
             var m = new ctx.FP8(this.a), 
                 t = new ctx.FP8(0);
@@ -136,50 +215,87 @@
             this.norm();
         },
 
-        /* this=conjugate(this) */
+	/**
+         * Conjugation of FP16
+         *
+         * @this {FP16}
+         */
         conj: function() {
             this.b.neg();
             this.norm();
         },
 
-        /* this=-conjugate(this) */
+	/**
+         * Negative conjugation of FP16
+         *
+         * @this {FP16}
+         */
         nconj: function() {
             this.a.neg();
             this.norm();
         },
 
-        /* this+=x */
+	/**
+         * addition of two FP16s
+         *
+         * @this {FP16}
+         * @param x FP16 instance
+         */
         add: function(x) {
             this.a.add(x.a);
             this.b.add(x.b);
         },
 
-        /* this-=x */
+	/**
+         * subtraction of two FP16s
+         *
+         * @this {FP16}
+         * @param x FP16 instance
+         */
         sub: function(x) {
             var m = new FP16(x); 
             m.neg();
             this.add(m);
         },
 
-        /* this*=s where s is FP8 */
+	/**
+         * Multiplication of an FP16 by an FP8
+         *
+         * @this {FP16}
+         * @param s FP8 instance
+         */
         pmul: function(s) {
             this.a.mul(s);
             this.b.mul(s);
         },
 
-        /* this*=s where s is FP2 */
+	/**
+         * Multiplication of an FP16 by an FP2
+         *
+         * @this {FP16}
+         * @param s FP2 instance
+         */
         qmul: function(s) {
             this.a.qmul(s);
             this.b.qmul(s);
         },
 
-        /* this*=c where s is int */
+	/**
+         * Multiplication of an FP16 by a small integer
+         *
+         * @this {FP16}
+         * @param s integer
+         */
         imul: function(c) {
             this.a.imul(c);
             this.b.imul(c);
         },
 
-        /* this*=this */
+	/**
+         * Fast Squaring of an FP16
+         *
+         * @this {FP16}
+         */
         sqr: function() {
             var t1 = new ctx.FP8(this.a), 
                 t2 = new ctx.FP8(this.b), 
@@ -210,7 +326,12 @@
             this.norm();
         },
 
-        /* this*=y */
+	/**
+         * Full unconditional Multiplication of two FP16s
+         *
+         * @this {FP16}
+         * @param y FP16 instance, the multiplier
+         */
         mul: function(y) {
 
             var t1 = new ctx.FP8(this.a), 
@@ -245,12 +366,20 @@
             this.norm();
         },
 
-        /* convert to hex string */
+	/**
+         * convert this to hex string
+         *
+         * @this {FP16}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "]");
         },
 
-        /* this=1/this */
+	/**
+         * Inverting an FP16
+         *
+         * @this {FP16}
+         */
         inverse: function() {
             //this.norm();
 
@@ -269,7 +398,11 @@
             this.b.mul(t1);
         },
 
-        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+	/**
+         * multiplies an FP16 instance by irreducible polynomial sqrt(1+sqrt(-1))
+         *
+         * @this {FP16}
+         */
         times_i: function() {
             var s = new ctx.FP8(this.b),
                 t = new ctx.FP8(this.a);
@@ -281,18 +414,33 @@
             this.norm();
         },
 
+	/**
+         * multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+         *
+         * @this {FP16}
+         */
         times_i2: function() {
             this.a.times_i();
             this.b.times_i();
         },
 
+	/**
+         * multiplies an FP16 instance by irreducible polynomial (1+sqrt(-1))
+         *
+         * @this {FP16}
+         */
         times_i4: function() {
             this.a.times_i2();
             this.b.times_i2();
         },
 
 
-        /* this=this^q using Frobenius, where q is Modulus */
+	/**
+         * Raises an FP16 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP16}
+         * @param f Modulus
+         */
         frob: function(f) {
             var ff=new ctx.FP2(f); ff.sqr(); ff.norm();
             this.a.frob(ff);
@@ -301,7 +449,12 @@
             this.b.times_i();
         },
 
-        /* this=this^e */
+	/**
+         * Raises an FP16 to the power of a BIG
+         *
+         * @this {FP16}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             
             var w = new FP16(this), 
@@ -329,7 +482,14 @@
             return r;
         },
 
-        /* XTR xtr_a function */
+	/**
+         * Calculates the XTR addition function r=w*x-conj(x)*y+z
+         *
+         * @this {FP16}
+         * @param w FP16 instance
+         * @param y FP16 instance
+         * @param z FP16 instance
+         */
         xtr_A: function(w, y, z) {
             var r = new FP16(w), 
                 t = new FP16(w); 
@@ -349,7 +509,11 @@
             this.reduce();
         },
 
-        /* XTR xtr_d function */
+	/**
+         * Calculates the XTR doubling function r=x^2-2*conj(x)
+         *
+         * @this {FP16}
+         */
         xtr_D: function() {
             var w = new FP16(this); 
             this.sqr();
@@ -359,7 +523,12 @@
             this.reduce();
         },
 
-        /* r=x^n using XTR method on traces of FP12s */
+	/**
+         * Calculates FP16 trace of an FP16 raised to the power of a BIG number
+         *
+         * @this {FP16}
+         * @param n Big number
+         */
         xtr_pow: function(n) {
 			var sf = new FP16(this);
 			sf.norm();
@@ -414,7 +583,11 @@
             return r;
         },
 
-        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	/**
+         * Calculates FP16 trace of c^a.d^b, where c and d are derived from FP16 traces of FP16s
+         *
+         * @this {FP16}
+         */
         xtr_pow2: function(ck, ckml, ckm2l, a, b) {
 
             var e = new ctx.BIG(a), 
diff --git a/src/fp2.js b/src/fp2.js
index d2d1a50..70b0477 100644
--- a/src/fp2.js
+++ b/src/fp2.js
@@ -24,7 +24,12 @@
 var FP2 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP2.
+      *
+      * @constructor
+      * @this {FP2}
+      */
     var FP2 = function(c, d) {
         if (c instanceof FP2) {
             this.a = new ctx.FP(c.a);
@@ -36,93 +41,170 @@
     };
 
     FP2.prototype = {
-        /* reduce components mod Modulus */
+
+	/**
+         * Reduces all components of possibly unreduced FP2 mod Modulus
+         *
+         * @this {FP2}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
         },
 
-        /* normalise components of w */
+	/**
+         * Normalises the components of an FP2
+         *
+         * @this {FP2}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
         },
 
-        /* test this=0 ? */
+	/**
+         * Tests for FP2 equal to zero
+         *
+         * @this {FP2}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch());
         },
 
-        /* test this=1 ? */
+	/**
+         * Tests for FP2 equal to unity
+         *
+         * @this {FP2}
+         */
         isunity: function() {
             var one = new ctx.FP(1);
             return (this.a.equals(one) && this.b.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP2 number
+         *
+         * @this {FP2}
+         * @param g FP2 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
         },
 
-        /* test this=x */
+	/**
+         * Tests for equality of two FP2 instances
+         *
+         * @this {FP2}
+         * @param x FP2 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b));
         },
 
-        /* extract a */
+	/**
+         * extract a from this
+         *
+         * @this {FP2}
+         */	
         getA: function() {
             return this.a.redc();
         },
 
-        /* extract b */
+	/**
+         * extract b from this
+         *
+         * @this {FP2}
+         */	
         getB: function() {
             return this.b.redc();
         },
 
-        /* set from pair of FPs */
+	/**
+         * Set FP2 from two FP values
+         *
+         * @this {FP2}
+         * @param c FP instance
+         * @param d FP instance
+         */
         set: function(c, d) {
             this.a.copy(c);
             this.b.copy(d);
         },
 
-        /* set a */
+	/**
+         * Set FP2 from one FP value
+         *
+         * @this {FP2}
+         * @param c FP instance
+         */
         seta: function(c) {
             this.a.copy(c);
             this.b.zero();
         },
 
-        /* set from two BIGs */
+	/**
+         * Set FP2 from two BIG values
+         *
+         * @this {FP2}
+         * @param c BIG instance
+         * @param d BIG instance
+         */
         bset: function(c, d) {
             this.a.bcopy(c);
             this.b.bcopy(d);
         },
 
-        /* set from one ctx.BIG */
+	/**
+         * Set FP2 from one BIG value
+         *
+         * @this {FP2}
+         * @param c BIG instance
+         */
         bseta: function(c) {
             this.a.bcopy(c);
             this.b.zero();
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP2 to another FP2
+         *
+         * @this {FP2}
+         * @param x FP2 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
         },
 
-        /* set this=0 */
+	/**
+         * Set FP2 to zero
+         *
+         * @this {FP2}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
         },
 
-        /* set this=1 */
+	/**
+         * Set FP2 to unity
+         *
+         * @this {FP2}
+         * @param x FP2 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
         },
 
-        /* negate this */
+	/**
+         * negate this
+         *
+         * @this {FP2}
+         * @param x FP2 instance to be set to one
+         */
         neg: function() {
             var m = new ctx.FP(this.a),
                 t = new ctx.FP(0);
@@ -136,19 +218,33 @@
             this.a.copy(t);
         },
 
-        /* conjugate this */
+	/**
+         * Conjugation of FP2
+         *
+         * @this {FP2}
+         */
         conj: function() {
             this.b.neg();
             this.b.norm();
         },
 
-        /* this+=a */
+	/**
+         * addition of two FP2s
+         *
+         * @this {FP2}
+         * @param x FP2 instance
+         */
         add: function(x) {
             this.a.add(x.a);
             this.b.add(x.b);
         },
 
-        /* this-=x */
+	/**
+         * subtraction of two FP2s
+         *
+         * @this {FP2}
+         * @param x FP2 instance
+         */
         sub: function(x) {
             var m = new FP2(x); 
             m.neg();
@@ -160,19 +256,33 @@
             this.add(x);
         },
 
-        /* this*=s, where s is FP */
+	/**
+         * Multiplication of an FP2 by an FP8
+         *
+         * @this {FP2}
+         * @param s FP8 instance
+         */
         pmul: function(s) {
             this.a.mul(s);
             this.b.mul(s);
         },
 
-        /* this*=c, where s is int */
+	/**
+         * Multiplication of an FP2 by a small integer
+         *
+         * @this {FP2}
+         * @param s integer
+         */
         imul: function(c) {
             this.a.imul(c);
             this.b.imul(c);
         },
 
-        /* this*=this */
+	/**
+         * Fast Squaring of an FP2
+         *
+         * @this {FP2}
+         */
         sqr: function() {
             var w1 = new ctx.FP(this.a),
                 w3 = new ctx.FP(this.a),
@@ -192,8 +302,12 @@
             this.a.mul(w1);
         },
 
-        /* this*=y */
-        /* Now using Lazy reduction - inputs must be normed */
+	/**
+         * Full unconditional Multiplication of two FP2s
+         *
+         * @this {FP2}
+         * @param y FP2 instance, the multiplier
+         */
         mul: function(y) {
             var p = new ctx.BIG(0),
                 pR = new ctx.DBIG(0),
@@ -240,8 +354,12 @@
             this.b.XES = 2;
         },
 
-        /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
-        /* returns true if this is QR */
+	/**
+         * sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) 
+         *
+         * @this {FP2}
+         * @return true if this is QR 
+         */	
         sqrt: function() {
             var w1, w2;
 
@@ -283,12 +401,20 @@
             return true;
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string
+         *
+         * @this {FP2}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "]");
         },
 
-        /* this=1/this */
+	/**
+         * Inverting an FP2
+         *
+         * @this {FP2}
+         */
         inverse: function() {
             var w1, w2;
 
@@ -307,13 +433,21 @@
             this.b.mul(w1);
         },
 
-        /* this/=2 */
+	/**
+         * Divide an FP2 by 2
+         *
+         * @this {FP2}
+         */
         div2: function() {
             this.a.div2();
             this.b.div2();
         },
 
-        /* this*=sqrt(-1) */
+	/**
+         * Multiply an FP2 by sqrt(-1)
+         *
+         * @this {FP2}
+         */
         times_i: function() {
             var z = new ctx.FP(this.a); //z.copy(this.a);
             this.a.copy(this.b);
@@ -321,8 +455,11 @@
             this.b.copy(z);
         },
 
-        /* w*=(1+sqrt(-1)) */
-        /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
+	/**
+         * Multiply an FP2 by (1+sqrt(-1))
+         *
+         * @this {FP2}
+         */	
         mul_ip: function() {
             var t = new FP2(this), 
                 z = new ctx.FP(this.a);
@@ -334,6 +471,11 @@
             //      this.norm();
         },
 
+	/**
+         * Divide an FP2 by (1+sqrt(-1))/2 
+         *
+         * @this {FP2}
+         */	
         div_ip2: function() {
             var t = new FP2(0);
             this.norm();
@@ -345,7 +487,11 @@
             this.norm();
         },
 
-        /* w/=(1+sqrt(-1)) */
+	/**
+         * Divide an FP2 by (1+sqrt(-1))
+         *
+         * @this {FP2}
+         */	
         div_ip: function() {
             var t = new FP2(0);
             this.norm();
@@ -358,7 +504,12 @@
             this.div2();
         },
 
-        /* this=this^e */
+	/**
+         * Raises an FP2 to the power of a BIG
+         *
+         * @this {FP2}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             this.norm();
 
diff --git a/src/fp24.js b/src/fp24.js
index 50cd3d2..97ece0c 100644
--- a/src/fp24.js
+++ b/src/fp24.js
@@ -24,7 +24,12 @@
 var FP24 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP24.
+      *
+      * @constructor
+      * @this {FP24}
+      */
     var FP24 = function(d, e, f) {
 		if (!isNaN(d))
 		{
@@ -50,32 +55,55 @@
     };
 
     FP24.prototype = {
-        /* reduce all components of this mod Modulus */
+
+	/**
+         * Reduces all components of possibly unreduced FP24 mod Modulus
+         *
+         * @this {FP24}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
             this.c.reduce();
         },
 
-        /* normalize all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP24
+         *
+         * @this {FP24}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
             this.c.norm();
         },
 
-        /* test x==0 ? */
+	/**
+         * Tests for FP24 equal to zero
+         *
+         * @this {FP24}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
         },
 
-        /* test x==1 ? */
+	/**
+         * Tests for FP24 equal to unity
+         *
+         * @this {FP24}
+         */
         isunity: function() {
             var one = new ctx.FP8(1);
             return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP24 number
+         *
+         * @this {FP24}
+         * @param g FP24 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
@@ -84,7 +112,11 @@
 			this.stype^=(this.stype^g.stype)&d;
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {FP24}
+         */
         select: function(g, b) {
             var invf = new FP24(0),
                 m, babs;
@@ -114,27 +146,50 @@
 		gettype: function() {
 			return this.stype;
 		},
-        /* extract a from this */
+	
+	/**
+         * extract a from this
+         *
+         * @this {FP24}
+         */	
         geta: function() {
             return this.a;
         },
 
-        /* extract b */
+	/**
+         * extract b from this
+         *
+         * @this {FP24}
+         */
         getb: function() {
             return this.b;
         },
 
-        /* extract c */
+	/**
+         * extract c from this
+         *
+         * @this {FP24}
+         */
         getc: function() {
             return this.c;
         },
 
-        /* return 1 if x==y, else 0 */
+	/**
+         * Tests for equality of two FP24s
+         *
+         * @this {FP24}
+         * @param x FP24 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP24 to another FP24
+         *
+         * @this {FP24}
+         * @param x FP24 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
@@ -142,7 +197,12 @@
 			this.stype=x.stype;
         },
 
-        /* set this=1 */
+	/**
+         * Set FP24 to unity
+         *
+         * @this {FP24}
+         * @param x FP24 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
@@ -150,7 +210,11 @@
 			this.stype=ctx.FP.ONE;
         },
 
-        /* set this=0 */
+	/**
+         * Set FP24 to zero
+         *
+         * @this {FP24}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
@@ -158,14 +222,25 @@
 			this.stype=ctx.FP.ZERO;
         },
 
-        /* this=conj(this) */
+	/**
+         * Conjugation of FP24
+         *
+         * @this {FP24}
+         */
         conj: function() {
             this.a.conj();
             this.b.nconj();
             this.c.conj();
         },
 
-        /* set this from 3 FP8s */
+	/**
+         * Set FP24 from three FP8 values
+         *
+         * @this {FP24}
+         * @param d FP8 instance
+         * @param e FP8 instance
+         * @param f FP8 instance
+         */
         set: function(d, e, f) {
             this.a.copy(d);
             this.b.copy(e);
@@ -173,7 +248,12 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* set this from one ctx.FP8 */
+	/**
+         * Set FP24 from one FP8 value
+         *
+         * @this {FP24}
+         * @param c FP8 instance
+         */
         seta: function(d) {
             this.a.copy(d);
             this.b.zero();
@@ -181,7 +261,11 @@
 			this.stype=ctx.FP.SPARSER
         },
 
-        /* Granger-Scott Unitary Squaring */
+	/**
+         * Fast Squaring of an FP24 in "unitary" form
+         *
+         * @this {FP24}
+         */
         usqr: function() {
             var A = new ctx.FP8(this.a), 
                 B = new ctx.FP8(this.c), 
@@ -220,7 +304,11 @@
             this.reduce();
         },
 
-        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	/**
+         * Fast Squaring of an FP24
+         *
+         * @this {FP24}
+         */
         sqr: function() {
 			if (this.stype==ctx.FP.ONE)
 				return;
@@ -262,7 +350,12 @@
             this.norm();
         },
 
-        /* FP24 full multiplication this=this*y */
+	/**
+         * Full unconditional Multiplication of two FP24s
+         *
+         * @this {FP24}
+         * @param y FP24 instance, the multiplier
+         */
         mul: function(y) {
             var z0 = new ctx.FP8(this.a), 
                 z1 = new ctx.FP8(0),
@@ -336,8 +429,15 @@
 
 /* FP24 multiplication w=w*y */
 /* catering for special case that arises from special form of ATE pairing line function */
-/* w and y are both sparser line functions - cost = 6m */ 
-		smul: function(y) {
+	/* w and y are both sparser line functions - cost = 6m */
+
+	/**
+         * Fast multiplication of two sparse FP24s that arises from ATE pairing line functions
+         *
+         * @this {FP24}
+         * @param y FP24 instance, the multiplier
+         */	
+	smul: function(y) {
 			if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
 			{	
 				var w1=new ctx.FP4(this.a.geta());
@@ -447,8 +547,15 @@
 
 /* FP24 full multiplication w=w*y */
 /* Supports sparse multiplicands */
-/* Usually w is denser than y */
-		ssmul: function(y) {
+	/* Usually w is denser than y */
+
+	/**
+         * Fast multiplication of what may be sparse multiplicands
+         *
+         * @this {FP24}
+         * @param y FP24 instance, the multiplier
+         */
+	ssmul: function(y) {
 			if (this.stype==ctx.FP.ONE)
 			{
 				this.copy(y);
@@ -642,7 +749,11 @@
 			this.norm();
 		},
 
-        /* this=1/this */
+	/**
+         * Inverting an FP24
+         *
+         * @this {FP24}
+         */
         inverse: function() {
             var f0 = new ctx.FP8(this.a), 
                 f1 = new ctx.FP8(this.b), 
@@ -689,7 +800,12 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* this=this^p, where p=Modulus, using Frobenius */
+	/**
+         * Raises an FP24 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP24}
+         * @param f Modulus
+         */
         frob: function(f,n) {
             var f2 = new ctx.FP2(f),
                 f3 = new ctx.FP2(f),
@@ -711,7 +827,11 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* trace function */
+	/**
+         * Calculate the trace of an FP24
+         *
+         * @this {FP24}
+         */
         trace: function() {
             var t = new ctx.FP8(0);
 
@@ -722,12 +842,21 @@
             return t;
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string
+         *
+         * @this {FP24}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte array
+         *
+         * @this {FP24}
+         * @param w Byte array
+         */
         toBytes: function(w) {
             var t = [],
                 i;
@@ -835,7 +964,12 @@
             }
         },
 
-        /* set this=this^e */
+	/**
+         * Raises an FP24 to the power of a BIG
+         *
+         * @this {FP24}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var e1, e3, w, nb, i, bt, sf;
 
@@ -869,7 +1003,13 @@
             return w;
         },
 
-        /* constant time powering by small integer of max length bts */
+	/**
+         * Raises an FP24 instance x to a small integer power, side-channel resistant
+         *
+         * @this {FP24}
+         * @param e small integer exponent
+         * @param bts maximum number of bits in exponent
+         */
         pinpow: function(e, bts) {
             var R = [],
                 i, b;
@@ -886,7 +1026,13 @@
             this.copy(R[0]);
         },
 
-        /* Faster compressed powering for unitary elements */
+	/**
+         * Raises an FP24 instance to a BIG power, compressed to FP4
+         *
+         * @this {FP24}
+         * @param e BIG exponent
+         * @param r BIG group order
+         */
         compow: function(e, r) {
             var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
 
@@ -933,7 +1079,12 @@
         }
     };
 
-    /* convert from byte array to FP12 */
+    /**
+      * convert from byte array to FP24 
+      *
+      * @this {FP24}
+      * @param w Byte array
+      */    
     FP24.fromBytes = function(w) {
         var t = [],
             i, a, b, c, d, e, f, g, r, ea, eb;
@@ -1081,7 +1232,11 @@
         return r;
     };
 
-    /* return 1 if b==c, no branching */
+    /**
+      * return 1 if b==c, no branching 
+      *
+      * @this {FP24}
+      */    
     FP24.teq = function(b, c) {
         var x = b ^ c;
         x -= 1; // if x=0, x now -1
@@ -1092,6 +1247,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * p=q0^u0.q1^u1.q2^u2.q3^u3... 
+      *
+      * @this {FP24}
+      */    
     FP24.pow8 = function(q, u) {
         var g1 = [],
             g2 = [],
diff --git a/src/fp4.js b/src/fp4.js
index 12c7c97..2ad664e 100644
--- a/src/fp4.js
+++ b/src/fp4.js
@@ -24,7 +24,12 @@
 var FP4 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP4
+      *
+      * @constructor
+      * @this {FP4}
+      */
     var FP4 = function(c, d) {
         if (c instanceof FP4) {
             this.a = new ctx.FP2(c.a);
@@ -36,90 +41,164 @@
     };
 
     FP4.prototype = {
-        /* reduce all components of this mod Modulus */
+	
+	/**
+         * Reduces all components of possibly unreduced FP4 mod Modulus
+         *
+         * @this {FP4}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
         },
 
-        /* normalise all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP4
+         *
+         * @this {FP4}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
         },
 
-        /* test this==0 ? */
+	/**
+         * Tests for FP4 equal to zero
+         *
+         * @this {FP4}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch());
         },
 
-        /* test this==1 ? */
+	/**
+         * Tests for FP4 equal to unity
+         *
+         * @this {FP4}
+         */
         isunity: function() {
             var one = new ctx.FP2(1);
             return (this.a.equals(one) && this.b.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP4 number
+         *
+         * @this {FP4}
+         * @param g FP4 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
         },
 
-        /* test is w real? That is in a+ib test b is zero */
+	/**
+         * test is w real? That is in a+ib test b is zero 
+         *
+         * @this {FP4}
+         */
         isreal: function() {
             return this.b.iszilch();
         },
 
-        /* extract real part a */
+	/**
+         * extract real part a
+         *
+         * @this {FP4}
+         */
         real: function() {
             return this.a;
         },
 
+	/**
+         * extract a from this
+         *
+         * @this {FP4}
+         */		
         geta: function() {
             return this.a;
         },
 
-        /* extract imaginary part b */
+	/**
+         * extract b from this
+         *
+         * @this {FP4}
+         */	
         getb: function() {
             return this.b;
         },
 
-        /* test this=x? */
+	/**
+         * Tests for equality of two FP4s
+         *
+         * @this {FP4}
+         * @param x FP4 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP4 to another FP4
+         *
+         * @this {FP4}
+         * @param x FP4 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
         },
 
-        /* this=0 */
+	/**
+         * Set FP4 to zero
+         *
+         * @this {FP4}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
         },
 
-        /* this=1 */
+	/**
+         * Set FP4 to unity
+         *
+         * @this {FP4}
+         * @param x FP4 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
         },
 
-        /* set from two FP2s */
+	/**
+         * Set FP4 from two FP2 values
+         *
+         * @this {FP4}
+         * @param c FP2 instance
+         * @param d FP2 instance
+         */
         set: function(c, d) {
             this.a.copy(c);
             this.b.copy(d);
         },
 
-        /* set a */
+	/**
+         * Set FP4 from one FP2 value
+         *
+         * @this {FP4}
+         * @param c FP2 instance
+         */
         seta: function(c) {
             this.a.copy(c);
             this.b.zero();
         },
 
-        /* this=-this */
+	/**
+         * Negation of FP4
+         *
+         * @this {FP4}
+         */
         neg: function() {
             this.norm();
             var m = new ctx.FP2(this.a), 
@@ -135,25 +214,43 @@
             this.norm();
         },
 
-        /* this=conjugate(this) */
+	/**
+         * Conjugation of FP4
+         *
+         * @this {FP4}
+         */
         conj: function() {
             this.b.neg();
             this.norm();
         },
 
-        /* this=-conjugate(this) */
+	/**
+         * Negative conjugation of FP4
+         *
+         * @this {FP4}
+         */
         nconj: function() {
             this.a.neg();
             this.norm();
         },
 
-        /* this+=x */
+	/**
+         * addition of two FP4s
+         *
+         * @this {FP4}
+         * @param x FP4 instance
+         */
         add: function(x) {
             this.a.add(x.a);
             this.b.add(x.b);
         },
 
-        /* this-=x */
+	/**
+         * subtraction of two FP4s
+         *
+         * @this {FP4}
+         * @param x FP4 instance
+         */
         sub: function(x) {
             var m = new FP4(x); 
             m.neg();
@@ -165,19 +262,33 @@
             this.add(x);
         },
 
-        /* this*=s where s is FP2 */
+	/**
+         * Multiplication of an FP4 by an FP8
+         *
+         * @this {FP4}
+         * @param s FP8 instance
+         */
         pmul: function(s) {
             this.a.mul(s);
             this.b.mul(s);
         },
 
-        /* this*=c where s is int */
+	/**
+         * Multiplication of an FP4 by an integer
+         *
+         * @this {FP4}
+         * @param s integer multiplier
+         */
         imul: function(c) {
             this.a.imul(c);
             this.b.imul(c);
         },
 
-        /* this*=this */
+	/**
+         * Fast Squaring of an FP4
+         *
+         * @this {FP4}
+         */
         sqr: function() {
             // this.norm();
 
@@ -211,7 +322,12 @@
             this.norm();
         },
 
-        /* this*=y */
+	/**
+         * Full unconditional Multiplication of two FP4s
+         *
+         * @this {FP4}
+         * @param y FP4 instance, the multiplier
+         */
         mul: function(y) {
             // this.norm();
 
@@ -247,12 +363,20 @@
             this.norm();
         },
 
-        /* convert to hex string */
+	/**
+         * convert to hex string
+         *
+         * @this {FP4}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "]");
         },
 
-        /* this=1/this */
+	/**
+         * Inverting an FP4
+         *
+         * @this {FP4}
+         */
         inverse: function() {
             this.norm();
 
@@ -271,7 +395,11 @@
             this.b.mul(t1);
         },
 
-        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+	/**
+         * multiplies an FP4 instance by irreducible polynomial sqrt(1+sqrt(-1))
+         *
+         * @this {FP4}
+         */
         times_i: function() {
             var s = new ctx.FP2(this.b), //s.copy(this.b);
                 t = new ctx.FP2(this.b); //t.copy(this.b);
@@ -283,14 +411,24 @@
             this.norm();
         },
 
-        /* this=this^q using Frobenius, where q is Modulus */
+	/**
+         * Raises an FP4 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP4}
+         * @param f Modulus
+         */
         frob: function(f) {
             this.a.conj();
             this.b.conj();
             this.b.mul(f);
         },
 
-        /* this=this^e */
+	/**
+         * Raises an FP4 to the power of a BIG
+         *
+         * @this {FP4}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var w = new FP4(this), 
                 z = new ctx.BIG(e), 
@@ -317,7 +455,14 @@
             return r;
         },
 
-        /* XTR xtr_a function */
+	/**
+         * Calculates the XTR addition function r=w*x-conj(x)*y+z
+         *
+         * @this {FP4}
+         * @param w FP4 instance
+         * @param y FP4 instance
+         * @param z FP4 instance
+         */
         xtr_A: function(w, y, z) {
             var r = new FP4(w), 
                 t = new FP4(w); 
@@ -338,7 +483,11 @@
             this.reduce();
         },
 
-        /* XTR xtr_d function */
+	/**
+         * Calculates the XTR doubling function r=x^2-2*conj(x)
+         *
+         * @this {FP4}
+         */
         xtr_D: function() {
             var w = new FP4(this); 
             this.sqr();
@@ -348,7 +497,12 @@
             this.reduce();
         },
 
-        /* r=x^n using XTR method on traces of FP12s */
+	/**
+         * Calculates FP4 trace of an FP4 raised to the power of a BIG number
+         *
+         * @this {FP4}
+         * @param n Big number
+         */
         xtr_pow: function(n) {
 			var sf = new FP4(this);
 			sf.norm();
@@ -404,7 +558,11 @@
             return r;
         },
 
-        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	/**
+         * Calculates FP4 trace of c^a.d^b, where c and d are derived from FP4 traces of FP4s
+         *
+         * @this {FP4}
+         */
         xtr_pow2: function(ck, ckml, ckm2l, a, b) {
  
             var e = new ctx.BIG(a), 
@@ -554,11 +712,21 @@
 
         /* New stuff for ecp4.js */
 
+	/**
+         * Divide an FP4 by 2
+         *
+         * @this {FP4}
+         */	
         div2: function() {
             this.a.div2();
             this.b.div2();
         },
 
+	/**
+         * Divide FP4 number by QNR
+         *
+         * @this {FP4}
+         */		
         div_i: function() {
             var u=new ctx.FP2(this.a),
                 v=new ctx.FP2(this.b);
@@ -567,6 +735,11 @@
             this.b.copy(u);
         },
 
+	/**
+         * Divide an FP4 by QNR/2
+         *
+         * @this {FP4}
+         */			
         div_2i: function() {
             var u=new ctx.FP2(this.a),
                 v=new ctx.FP2(this.b);
@@ -576,11 +749,22 @@
             this.b.copy(u);
         },
 
+	/**
+         * Multiplication of an FP4 by an FP
+         *
+         * @this {FP4}
+         * @param s FP multiplier
+         */				
         qmul: function(s) {
             this.a.pmul(s);
             this.b.pmul(s);
         },
 
+	/**
+         * Calculate square root of an FP4
+         *
+         * @this {FP4}
+         */					
         sqrt: function() {
             if (this.iszilch()) {
                 return true;
diff --git a/src/fp48.js b/src/fp48.js
index 58ac47b..c3e6704 100644
--- a/src/fp48.js
+++ b/src/fp48.js
@@ -24,7 +24,12 @@
 var FP48 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP48.
+      *
+      * @constructor
+      * @this {FP48}
+      */
     var FP48 = function(d, e, f) {
 		if (!isNaN(d))
 		{
@@ -50,32 +55,55 @@
     };
 
     FP48.prototype = {
-        /* reduce all components of this mod Modulus */
+	
+	/**
+         * Reduces all components of possibly unreduced FP48 mod Modulus
+         *
+         * @this {FP48}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
             this.c.reduce();
         },
 
-        /* normalize all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP48
+         *
+         * @this {FP48}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
             this.c.norm();
         },
 
-        /* test x==0 ? */
+	/**
+         * Tests for FP48 equal to zero
+         *
+         * @this {FP48}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch() && this.c.iszilch());
         },
 
-        /* test x==1 ? */
+	/**
+         * Tests for FP48 equal to unity
+         *
+         * @this {FP48}
+         */
         isunity: function() {
             var one = new ctx.FP16(1);
             return (this.a.equals(one) && this.b.iszilch() && this.c.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP48 number
+         *
+         * @this {FP48}
+         * @param g FP48 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
@@ -85,7 +113,11 @@
 
         },
 
-        /* Constant time select from pre-computed table */
+	/**
+         * Constant time select from pre-computed table 
+         *
+         * @this {FP48}
+         */
         select: function(g, b) {
             var invf = new FP48(0),
                 m, babs;
@@ -116,27 +148,49 @@
 			return this.stype;
 		},
 
-        /* extract a from this */
+	/**
+         * extract a from this
+         *
+         * @this {FP48}
+         */	
         geta: function() {
             return this.a;
         },
 
-        /* extract b */
+	/**
+         * extract b from this
+         *
+         * @this {FP48}
+         */
         getb: function() {
             return this.b;
         },
 
-        /* extract c */
+	/**
+         * extract c from this
+         *
+         * @this {FP48}
+         */
         getc: function() {
             return this.c;
         },
 
-        /* return 1 if x==y, else 0 */
+	/**
+         * Tests for equality of two FP48s
+         *
+         * @this {FP48}
+         * @param x FP48 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b) && this.c.equals(x.c));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP48 to another FP48
+         *
+         * @this {FP48}
+         * @param x FP48 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
@@ -144,7 +198,12 @@
 			this.stype=x.stype;
         },
 
-        /* set this=1 */
+	/**
+         * Set FP48 to unity
+         *
+         * @this {FP48}
+         * @param x FP48 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
@@ -152,7 +211,11 @@
 			this.stype=ctx.FP.ONE;
         },
 
-        /* set this=0 */
+	/**
+         * Set FP48 to zero
+         *
+         * @this {FP48}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
@@ -160,14 +223,25 @@
 			this.stype=ctx.FP.ZERO;
         },
 
-        /* this=conj(this) */
+	/**
+         * Conjugation of FP48
+         *
+         * @this {FP48}
+         */
         conj: function() {
             this.a.conj();
             this.b.nconj();
             this.c.conj();
         },
 
-        /* set this from 3 FP16s */
+	/**
+         * Set FP48 from three FP16 values
+         *
+         * @this {FP48}
+         * @param d FP16 instance
+         * @param e FP16 instance
+         * @param f FP16 instance
+         */
         set: function(d, e, f) {
             this.a.copy(d);
             this.b.copy(e);
@@ -175,7 +249,12 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* set this from one ctx.FP16 */
+	/**
+         * Set FP48 from one FP16 value
+         *
+         * @this {FP48}
+         * @param c FP16 instance
+         */
         seta: function(d) {
             this.a.copy(d);
             this.b.zero();
@@ -183,7 +262,11 @@
 			this.stype=ctx.FP.SPARSER
         },
 
-        /* Granger-Scott Unitary Squaring */
+	/**
+         * Fast Squaring of an FP48 in "unitary" form
+         *
+         * @this {FP48}
+         */
         usqr: function() {
             var A = new ctx.FP16(this.a), 
                 B = new ctx.FP16(this.c),
@@ -222,7 +305,11 @@
             this.reduce();
         },
 
-        /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
+	/**
+         * Fast Squaring of an FP48
+         *
+         * @this {FP48}
+         */
         sqr: function() {
 			if (this.stype==ctx.FP.ONE)
 				return;
@@ -264,7 +351,12 @@
             this.norm();
         },
 
-        /* FP48 full multiplication this=this*y */
+	/**
+         * Full unconditional Multiplication of two FP48s
+         *
+         * @this {FP48}
+         * @param y FP48 instance, the multiplier
+         */
         mul: function(y) {
             var z0 = new ctx.FP16(this.a), 
                 z1 = new ctx.FP16(0),
@@ -338,8 +430,15 @@
 
 /* FP48 multiplication w=w*y */
 /* catering for special case that arises from special form of ATE pairing line function */
-/* w and y are both sparser line functions - cost = 6m */ 
-		smul: function(y) {
+	/* w and y are both sparser line functions - cost = 6m */
+
+	/**
+         * Fast multiplication of two sparse FP48s that arises from ATE pairing line functions
+         *
+         * @this {FP48}
+         * @param y FP48 instance, the multiplier
+         */		
+	smul: function(y) {
 			if (ctx.ECP.SEXTIC_TWIST==ctx.ECP.D_TYPE)
 			{	
 				var w1=new ctx.FP8(this.a.geta());
@@ -449,8 +548,15 @@
 
 /* FP48 full multiplication w=w*y */
 /* Supports sparse multiplicands */
-/* Usually w is denser than y */
-		ssmul: function(y) {
+	/* Usually w is denser than y */
+
+	/**
+         * Fast multiplication of what may be sparse multiplicands
+         *
+         * @this {FP48}
+         * @param y FP48 instance, the multiplier
+         */	
+	ssmul: function(y) {
 			if (this.stype==ctx.FP.ONE)
 			{
 				this.copy(y);
@@ -645,7 +751,11 @@
 		},
 
 
-        /* this=1/this */
+	/**
+         * Inverting an FP48
+         *
+         * @this {FP48}
+         */
         inverse: function() {
             var f0 = new ctx.FP16(this.a), 
                 f1 = new ctx.FP16(this.b), 
@@ -692,7 +802,12 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* this=this^p, where p=Modulus, using Frobenius */
+	/**
+         * Raises an FP48 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP48}
+         * @param f Modulus
+         */
         frob: function(f,n) {
             var f2 = new ctx.FP2(f),
                 f3 = new ctx.FP2(f),
@@ -715,7 +830,11 @@
 			this.stype=ctx.FP.DENSE;
         },
 
-        /* trace function */
+	/**
+         * Calculate the trace of an FP48
+         *
+         * @this {FP48}
+         */
         trace: function() {
             var t = new ctx.FP16(0);
 
@@ -726,12 +845,21 @@
             return t;
         },
 
-        /* convert this to hex string */
+	/**
+         * convert this to hex string
+         *
+         * @this {FP48}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "," + this.c.toString() + "]");
         },
 
-        /* convert this to byte array */
+	/**
+         * convert this to byte array
+         *
+         * @this {FP48}
+         * @param w Byte array
+         */
         toBytes: function(w) {
             var t = [],
                 i;
@@ -941,7 +1069,12 @@
             }
         },
 
-        /* set this=this^e */
+	/**
+         * Raises an FP48 to the power of a BIG
+         *
+         * @this {FP48}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var e1, e3, w, nb, i, bt, sf;
 
@@ -975,7 +1108,13 @@
             return w;
         },
 
-        /* constant time powering by small integer of max length bts */
+	/**
+         * Raises an FP48 instance x to a small integer power, side-channel resistant
+         *
+         * @this {FP48}
+         * @param e small integer exponent
+         * @param bts maximum number of bits in exponent
+         */
         pinpow: function(e, bts) {
             var R = [],
                 i, b;
@@ -992,7 +1131,13 @@
             this.copy(R[0]);
         },
 
-        /* Faster compressed powering for unitary elements */
+	/**
+         * Raises an FP48 instance to a BIG power, compressed to FP4
+         *
+         * @this {FP48}
+         * @param e BIG exponent
+         * @param r BIG group order
+         */
         compow: function(e, r) {
             var fa, fb, f, q, m, a, b, g1, g2, c, cp, cpm1, cpm2;
 
@@ -1039,7 +1184,12 @@
         }
     };
 
-    /* convert from byte array to FP12 */
+    /**
+      * convert from byte array to FP48 
+      *
+      * @this {FP48}
+      * @param w Byte array
+      */    
     FP48.fromBytes = function(w) {
         var t = [],
             i, a, b, c, d, e, f, g, r, ea, eb, fa, fb;
@@ -1331,7 +1481,11 @@
         return r;
     };
 
-    /* return 1 if b==c, no branching */
+    /**
+      * return 1 if b==c, no branching 
+      *
+      * @this {FP48}
+      */    
     FP48.teq = function(b, c) {
         var x = b ^ c;
         x -= 1; // if x=0, x now -1
@@ -1342,6 +1496,12 @@
     // Bos & Costello https://eprint.iacr.org/2013/458.pdf
     // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
     // Side channel attack secure
+
+    /**
+      * p=q0^u0.q1^u1.q2^u2.q3^u3... 
+      *
+      * @this {FP48}
+      */        
     FP48.pow16 = function(q, u) {
         var g1 = [],
             g2 = [],
diff --git a/src/fp8.js b/src/fp8.js
index 21aa7bd..6e9ec98 100644
--- a/src/fp8.js
+++ b/src/fp8.js
@@ -24,7 +24,14 @@
 var FP8 = function(ctx) {
     "use strict";
 
-    /* general purpose constructor */
+    /**
+      * Creates an instance of FP8
+      *
+      * @constructor
+      * @this {FP4}
+      * @param c FP8 / FP4 instance
+      * @param d FP4 instance
+      */
     var FP8 = function(c, d) {
         if (c instanceof FP8) {
             this.a = new ctx.FP4(c.a);
@@ -36,90 +43,164 @@
     };
 
     FP8.prototype = {
-        /* reduce all components of this mod Modulus */
+	
+	/**
+         * Reduces all components of possibly unreduced FP8 mod Modulus
+         *
+         * @this {FP8}
+         */
         reduce: function() {
             this.a.reduce();
             this.b.reduce();
         },
 
-        /* normalise all components of this mod Modulus */
+	/**
+         * Normalises the components of an FP8
+         *
+         * @this {FP8}
+         */
         norm: function() {
             this.a.norm();
             this.b.norm();
         },
 
-        /* test this==0 ? */
+	/**
+         * Tests for FP8 equal to zero
+         *
+         * @this {FP8}
+         */
         iszilch: function() {
             return (this.a.iszilch() && this.b.iszilch());
         },
 
-        /* test this==1 ? */
+	/**
+         * Tests for FP8 equal to unity
+         *
+         * @this {FP8}
+         */
         isunity: function() {
             var one = new ctx.FP4(1);
             return (this.a.equals(one) && this.b.iszilch());
         },
 
-        /* conditional copy of g to this depending on d */
+	/**
+         * Conditional copy of FP8 number
+         *
+         * @this {FP8}
+         * @param g FP8 instance
+         * @param d copy depends on this value
+         */
         cmove: function(g, d) {
             this.a.cmove(g.a, d);
             this.b.cmove(g.b, d);
         },
 
-        /* test is w real? That is in a+ib test b is zero */
+	/**
+         * test is w real? That is in a+ib test b is zero 
+         *
+         * @this {FP8}
+         */
         isreal: function() {
             return this.b.iszilch();
         },
 
-        /* extract real part a */
+	/**
+         * extract real part a
+         *
+         * @this {FP8}
+         */
         real: function() {
             return this.a;
         },
 
+	/**
+         * extract a from this
+         *
+         * @this {FP8}
+         */		
         geta: function() {
             return this.a;
         },
 
-        /* extract imaginary part b */
+	/**
+         * extract b from this
+         *
+         * @this {FP8}
+         */	
         getb: function() {
             return this.b;
         },
 
-        /* test this=x? */
+	/**
+         * Tests for equality of two FP8s
+         *
+         * @this {FP8}
+         * @param x FP8 instance to compare
+         */
         equals: function(x) {
             return (this.a.equals(x.a) && this.b.equals(x.b));
         },
 
-        /* copy this=x */
+	/**
+         * Copy FP8 to another FP8
+         *
+         * @this {FP8}
+         * @param x FP8 instance to be copied
+         */
         copy: function(x) {
             this.a.copy(x.a);
             this.b.copy(x.b);
         },
 
-        /* this=0 */
+	/**
+         * Set FP8 to zero
+         *
+         * @this {FP8}
+         */
         zero: function() {
             this.a.zero();
             this.b.zero();
         },
 
-        /* this=1 */
+	/**
+         * Set FP8 to unity
+         *
+         * @this {FP8}
+         * @param x FP8 instance to be set to one
+         */
         one: function() {
             this.a.one();
             this.b.zero();
         },
 
-        /* set from two FP4s */
+	/**
+         * Set FP8 from two FP4 values
+         *
+         * @this {FP8}
+         * @param c FP4 instance
+         * @param d FP4 instance
+         */
         set: function(c, d) {
             this.a.copy(c);
             this.b.copy(d);
         },
 
-        /* set a */
+	/**
+         * Set FP8 from one FP4 value
+         *
+         * @this {FP8}
+         * @param c FP4 instance
+         */
         seta: function(c) {
             this.a.copy(c);
             this.b.zero();
         },
 
-        /* this=-this */
+	/**
+         * Negation of FP8
+         *
+         * @this {FP8}
+         */
         neg: function() {
             this.norm();
             var m = new ctx.FP4(this.a), 
@@ -135,25 +216,43 @@
             this.norm();
         },
 
-        /* this=conjugate(this) */
+	/**
+         * Conjugation of FP8
+         *
+         * @this {FP8}
+         */
         conj: function() {
             this.b.neg();
             this.norm();
         },
 
-        /* this=-conjugate(this) */
+	/**
+         * Negative conjugation of FP8
+         *
+         * @this {FP8}
+         */
         nconj: function() {
             this.a.neg();
             this.norm();
         },
 
-        /* this+=x */
+	/**
+         * addition of two FP8s
+         *
+         * @this {FP8}
+         * @param x FP8 instance
+         */
         add: function(x) {
             this.a.add(x.a);
             this.b.add(x.b);
         },
 
-        /* this-=x */
+	/**
+         * subtraction of two FP8s
+         *
+         * @this {FP8}
+         * @param x FP8 instance
+         */
         sub: function(x) {
             var m = new FP8(x); 
             m.neg();
@@ -165,19 +264,33 @@
             this.add(x);
         },
 
-        /* this*=s where s is FP4 */
+	/**
+         * Multiplication of an FP8 by an FP8
+         *
+         * @this {FP8}
+         * @param s FP8 instance
+         */
         pmul: function(s) {
             this.a.mul(s);
             this.b.mul(s);
         },
 
-        /* this*=c where s is int */
+	/**
+         * Multiplication of an FP8 by a small integer
+         *
+         * @this {FP8}
+         * @param s integer
+         */
         imul: function(c) {
             this.a.imul(c);
             this.b.imul(c);
         },
 
-        /* this*=this */
+	/**
+         * Fast Squaring of an FP8
+         *
+         * @this {FP8}
+         */
         sqr: function() {
             var t1 = new ctx.FP4(this.a), 
                 t2 = new ctx.FP4(this.b), 
@@ -208,7 +321,12 @@
             this.norm();
         },
 
-        /* this*=y */
+	/**
+         * Full unconditional Multiplication of two FP8s
+         *
+         * @this {FP8}
+         * @param y FP8 instance, the multiplier
+         */
         mul: function(y) {
             var t1 = new ctx.FP4(this.a), 
                 t2 = new ctx.FP4(this.b), 
@@ -242,12 +360,20 @@
             this.norm();
         },
 
-        /* convert to hex string */
+	/**
+         * convert to hex string
+         *
+         * @this {FP8}
+         */
         toString: function() {
             return ("[" + this.a.toString() + "," + this.b.toString() + "]");
         },
 
-        /* this=1/this */
+	/**
+         * Inverting an FP8
+         *
+         * @this {FP8}
+         */
         inverse: function() {
             this.norm();
 
@@ -266,7 +392,11 @@
             this.b.mul(t1);
         },
 
-        /* this*=i where i = sqrt(-1+sqrt(-1)) */
+	/**
+         * multiplies an FP8 instance by irreducible polynomial sqrt(1+sqrt(-1))
+         *
+         * @this {FP8}
+         */
         times_i: function() {
             var s = new ctx.FP4(this.b),
                 t = new ctx.FP4(this.a);
@@ -278,12 +408,22 @@
             this.norm();
         },
 
+	/**
+         * multiplies an FP8 instance by irreducible polynomial (1+sqrt(-1))
+         *
+         * @this {FP8}
+         */	
         times_i2: function() {
             this.a.times_i();
             this.b.times_i();
         },
 
-        /* this=this^q using Frobenius, where q is Modulus */
+	/**
+         * Raises an FP8 to the power of the internal modulus p, using the Frobenius
+         *
+         * @this {FP8}
+         * @param f Modulus
+         */
         frob: function(f) {
             var ff=new ctx.FP2(f); ff.sqr(); ff.mul_ip(); ff.norm();
             this.a.frob(ff);
@@ -292,7 +432,12 @@
             this.b.times_i();
         },
 
-        /* this=this^e */
+	/**
+         * Raises an FP8 to the power of a BIG
+         *
+         * @this {FP8}
+         * @param e BIG instance exponent
+         */
         pow: function(e) {
             var w = new FP8(this), 
                 z = new ctx.BIG(e), 
@@ -319,7 +464,14 @@
             return r;
         },
 
-        /* XTR xtr_a function */
+	/**
+         * Calculates the XTR addition function r=w*x-conj(x)*y+z
+         *
+         * @this {FP8}
+         * @param w FP8 instance
+         * @param y FP8 instance
+         * @param z FP8 instance
+         */
         xtr_A: function(w, y, z) {
             var r = new FP8(w), 
                 t = new FP8(w); 
@@ -339,7 +491,11 @@
             this.reduce();
         },
 
-        /* XTR xtr_d function */
+	/**
+         * Calculates the XTR doubling function r=x^2-2*conj(x)
+         *
+         * @this {FP8}
+         */
         xtr_D: function() {
             var w = new FP8(this); //w.copy(this);
             this.sqr();
@@ -349,7 +505,12 @@
             this.reduce();
         },
 
-        /* r=x^n using XTR method on traces of FP12s */
+	/**
+         * Calculates FP8 trace of an FP8 raised to the power of a BIG number
+         *
+         * @this {FP8}
+         * @param n Big number
+         */
         xtr_pow: function(n) {
 			var sf = new FP8(this);
 			sf.norm();
@@ -404,7 +565,11 @@
             return r;
         },
 
-        /* r=ck^a.cl^n using XTR double exponentiation method on traces of FP12s. See Stam thesis. */
+	/**
+         * Calculates FP8 trace of c^a.d^b, where c and d are derived from FP8 traces of FP8s
+         *
+         * @this {FP8}
+         */
         xtr_pow2: function(ck, ckml, ckm2l, a, b) {
 
             var e = new ctx.BIG(a), 
@@ -554,11 +719,21 @@
 
         /* New stuff for ecp4.js */
 
+	/**
+         * Divide an FP8 by 2
+         *
+         * @this {FP8}
+         */		
         div2: function() {
             this.a.div2();
             this.b.div2();
         },
 
+	/**
+         * Divide FP8 number by QNR
+         *
+         * @this {FP8}
+         */			
         div_i: function() {
             var u=new ctx.FP4(this.a),
                 v=new ctx.FP4(this.b);
@@ -567,11 +742,21 @@
             this.b.copy(u);
         },
 
+	/**
+         * Divide an FP8 by QNR twice
+         *
+         * @this {FP8}
+         */						
         div_i2: function() {
             this.a.div_i();
             this.b.div_i();
         },
 
+	/**
+         * Divide an FP8 by QNR/2
+         *
+         * @this {FP8}
+         */					
         div_2i: function() {
             var u=new ctx.FP4(this.a),
                 v=new ctx.FP4(this.b);
@@ -581,16 +766,33 @@
             this.b.copy(u);
         },
 
+	/**
+         * Multiplication of an FP8 by an FP2
+         *
+         * @this {FP8}
+         * @param s FP2 multiplier
+         */					
         qmul: function(s) {
             this.a.pmul(s);
             this.b.pmul(s);
         },
 
+	/**
+         * Multiplication of an FP8 by an FP
+         *
+         * @this {FP8}
+         * @param s FP multiplier
+         */						
         tmul: function(s) {
             this.a.qmul(s);
             this.b.qmul(s);
         },
 
+	/**
+         * Calculate square root of an FP8
+         *
+         * @this {FP8}
+         */						
         sqrt: function() {
             if (this.iszilch()) {
                 return true;
diff --git a/src/gcm.js b/src/gcm.js
index 0591972..a77eb87 100644
--- a/src/gcm.js
+++ b/src/gcm.js
@@ -39,6 +39,12 @@
 var GCM = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of GCM
+      *
+      * @constructor
+      * @this {GCM}
+      */    
     var GCM = function() {
         this.table = new Array(128);
         for (var i = 0; i < 128; i++) {
@@ -63,6 +69,7 @@
     GCM.DECRYPTING = 1;
 
     GCM.prototype = {
+	
         precompute: function(H) {
             var b = [],
                 i, j, c;
@@ -148,7 +155,15 @@
             this.gf2mul();
         },
 
-        /* Initialize GCM mode */
+	/**
+         * Initialize GCM mode 
+         *
+         * @this {GCM}
+	 * @param nk is the key length in bytes, 16, 24 or 32
+	 * @param key the AES key as an array of 16 bytes
+	 * @param niv the number of bytes in the Initialisation Vector (IV)
+	 * @param iv the IV
+         */
         init: function(nk, key, niv, iv) { /* iv size niv is usually 12 bytes (96 bits). ctx.AES key size nk can be 16,24 or 32 bytes */
             var H = [],
                 b = [],
@@ -196,7 +211,13 @@
             this.status = GCM.ACCEPTING_HEADER;
         },
 
-        /* Add Header data - included but not encrypted */
+	/**
+         * Add header (material to be authenticated but not encrypted)
+         *
+         * @this {GCM}
+	 * @param header is the header material to be added
+	 * @param len the number of bytes in the header
+         */
         add_header: function(header, len) { /* Add some header. Won't be encrypted, but will be authenticated. len is length of header */
             var i, j = 0;
 
@@ -256,7 +277,14 @@
             return true;
         },
 
-        /* Add Plaintext - included and encrypted */
+	/**
+         * Add plaintext and extract ciphertext
+         *
+         * @this {GCM}
+	 * @param plain is the plaintext material to be added
+	 * @param len the number of bytes in the plaintext
+         * @return cipher is the ciphertext generated
+         */
         add_plain: function(plain, len) {
             var B = [],
                 b = [],
@@ -311,7 +339,14 @@
             return cipher;
         },
 
-        /* Add Ciphertext - decrypts to plaintext */
+	/**
+         * Add Ciphertext - decrypts to plaintext
+         *
+         * @this {GCM}
+	 * @param cipher is the ciphertext to be added
+	 * @param len the number of bytes in the plaintext
+         * @return plain is the plaintext material generated
+         */
         add_cipher: function(cipher, len) {
             var B = [],
                 b = [],
@@ -369,6 +404,12 @@
             return plain;
         },
 
+	/**
+         * Finish off and extract authentication tag (HMAC)
+         *
+         * @this {GCM}
+         * @return tag is the output 16 byte authentication tag
+         */
         /* Finish and extract Tag */
         finish: function(extract) { /* Finish off GHASH and extract tag (MAC) */
             var tag = [],
diff --git a/src/hash256.js b/src/hash256.js
index 99b36f2..b0d3000 100644
--- a/src/hash256.js
+++ b/src/hash256.js
@@ -20,6 +20,12 @@
 var HASH256 = function() {
     "use strict";
 
+    /**
+      * Creates an instance of HASH256
+      *
+      * @constructor
+      * @this {HASH256}
+      */    
     var HASH256 = function() {
         this.length = [];
         this.h = [];
@@ -28,6 +34,7 @@
     };
 
     HASH256.prototype = {
+
         transform: function() { /* basic transformation step */
             var a, b, c, d, e, f, g, hh, t1, t2, j;
 
@@ -68,7 +75,11 @@
 
         },
 
-        /* Initialise Hash function */
+	/**
+         * Initialise Hash function
+         *
+         * @this {HASH256}
+         */	
         init: function() { /* initialise */
             var i;
 
@@ -86,7 +97,12 @@
             this.h[7] = HASH256.H[7];
         },
 
-        /* process a single byte */
+	/**
+         * Process a single byte
+         *
+         * @this {HASH256}
+         * @param byt byte to be included in hash
+         */	
         process: function(byt) { /* process the next message byte */
             var cnt;
 
@@ -105,14 +121,24 @@
             }
         },
 
-        /* process an array of bytes */
+	/**
+         * Process an array of bytes
+         *
+         * @this {HASH256}
+         * @param b byte arrray to be included in hash
+         */	
         process_array: function(b) {
             for (var i = 0; i < b.length; i++) {
                 this.process(b[i]);
             }
         },
 
-        /* process a 32-bit integer */
+	/**
+         * Process a 32-bit integer 
+         *
+         * @this {HASH256}
+         * @param n Integer to be included in hash
+         */	
         process_num: function(n) {
             this.process((n >> 24) & 0xff);
             this.process((n >> 16) & 0xff);
@@ -120,6 +146,12 @@
             this.process(n & 0xff);
         },
 
+	/**
+         * Generate 32-byte hash
+         *
+         * @this {HASH256}
+         * @return digest 32-byte hash
+         */		
         hash: function() { /* pad message and finish - supply digest */
             var digest = [],
                 len0, len1, i;
diff --git a/src/hash384.js b/src/hash384.js
index 9c2941d..405f7c6 100644
--- a/src/hash384.js
+++ b/src/hash384.js
@@ -20,6 +20,12 @@
 var HASH384 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of HASH384
+      *
+      * @constructor
+      * @this {HASH384}
+      */        
     var HASH384 = function() {
         this.length = [];
         this.h = [];
@@ -73,7 +79,11 @@
             this.h[7].add(hh);
         },
 
-        /* Initialise Hash function */
+	/**
+         * Initialise Hash function
+         *
+         * @this {HASH384}
+         */	
         init: function() { /* initialise */
             var i;
 
@@ -92,7 +102,12 @@
             this.h[7] = HASH384.H[7].copy();
         },
 
-        /* process a single byte */
+	/**
+         * Process a single byte
+         *
+         * @this {HASH384}
+         * @param byt byte to be included in hash
+         */	
         process: function(byt) { /* process the next message byte */
             var cnt, e;
 
@@ -113,14 +128,24 @@
             }
         },
 
-        /* process an array of bytes */
+	/**
+         * Process an array of bytes
+         *
+         * @this {HASH384}
+         * @param b byte arrray to be included in hash
+         */	
         process_array: function(b) {
             for (var i = 0; i < b.length; i++) {
                 this.process(b[i]);
             }
         },
 
-        /* process a 32-bit integer */
+	/**
+         * Process a 32-bit integer 
+         *
+         * @this {HASH384}
+         * @param n Integer to be included in hash
+         */	
         process_num: function(n) {
             this.process((n >> 24) & 0xff);
             this.process((n >> 16) & 0xff);
@@ -128,6 +153,12 @@
             this.process(n & 0xff);
         },
 
+	/**
+         * Generate 32-byte hash
+         *
+         * @this {HASH384}
+         * @return digest 32-byte hash
+         */			
         hash: function() { /* pad message and finish - supply digest */
             var digest = [],
                 len0, len1,
diff --git a/src/hash512.js b/src/hash512.js
index eb468a6..bede51a 100644
--- a/src/hash512.js
+++ b/src/hash512.js
@@ -20,6 +20,12 @@
 var HASH512 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of HASH512
+      *
+      * @constructor
+      * @this {HASH512}
+      */            
     var HASH512 = function() {
         this.length = [];
         this.h = [];
@@ -74,7 +80,11 @@
             this.h[7].add(hh);
         },
 
-        /* Initialise Hash function */
+	/**
+         * Initialise Hash function
+         *
+         * @this {HASH512}
+         */	
         init: function() { /* initialise */
             var i;
 
@@ -94,7 +104,12 @@
             this.h[7] = HASH512.H[7].copy();
         },
 
-        /* process a single byte */
+	/**
+         * Process a single byte
+         *
+         * @this {HASH512}
+         * @param byt byte to be included in hash
+         */	
         process: function(byt) { /* process the next message byte */
             var cnt, e;
 
@@ -115,14 +130,24 @@
             }
         },
 
-        /* process an array of bytes */
+	/**
+         * Process an array of bytes
+         *
+         * @this {HASH512}
+         * @param b byte arrray to be included in hash
+         */	
         process_array: function(b) {
             for (var i = 0; i < b.length; i++) {
                 this.process(b[i]);
             }
         },
 
-        /* process a 32-bit integer */
+	/**
+         * Process a 32-bit integer 
+         *
+         * @this {HASH512}
+         * @param n Integer to be included in hash
+         */	
         process_num: function(n) {
             this.process((n >> 24) & 0xff);
             this.process((n >> 16) & 0xff);
@@ -130,6 +155,12 @@
             this.process(n & 0xff);
         },
 
+	/**
+         * Generate 32-byte hash
+         *
+         * @this {HASH512}
+         * @return digest 32-byte hash
+         */				
         hash: function() { /* pad message and finish - supply digest */
             var digest = [],
                 len0, len1, i;
diff --git a/src/mpin.js b/src/mpin.js
index 8988cc5..03df551 100644
--- a/src/mpin.js
+++ b/src/mpin.js
@@ -22,6 +22,12 @@
 var MPIN = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of MPIN
+      *
+      * @constructor
+      * @this {MPIN}
+      */            
     var MPIN = {
         BAD_PARAMS: -11,
         INVALID_POINT: -14,
@@ -43,12 +49,24 @@
         SHA384: 48,
         SHA512: 64,
 
-        /* return time in slots since epoch */
+	/**
+         * Get epoch time for today
+         *
+         * @this {MPIN}
+         * @return time in slots since epoch 
+         */	
         today: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
         },
 
+	/**
+         * Convert byte array to string
+         *
+         * @this {MPIN}
+         * @param b byte array
+         * @return s string
+         */			
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -64,6 +82,13 @@
             return s;
         },
 
+	/**
+         * Convert a string to byte array
+         *
+         * @this {MPIN}
+         * @param s string
+         * @return b byte array
+         */				
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -75,6 +100,14 @@
             return b;
         },
 
+	/**
+         * Convert byte arrays
+         *
+         * @this {MPIN}
+         * @param a byte array
+         * @param b byte array
+         * @return true if equal
+         */					
         comparebytes: function(a, b) {
             if (a.length != b.length) {
                 return false;
@@ -89,6 +122,14 @@
             return true;
         },
 
+	/**
+         * Hash values
+         *
+         * @this {MPIN}
+         * @param c FP8 instance
+         * @param U ECP unstancebyte array
+         * @return R hash value
+         */						
         mpin_hash: function(sha, c, U) {
             var t = [],
                 w = [],
@@ -144,7 +185,15 @@
             return R;
         },
 
-        /* Hash number (optional) and string to point on curve */
+	/**
+         * General purpose hash function
+         *
+         * @this {MPIN}
+         * @param sha is the hash type
+         * @param n Integer
+         * @param B byte array
+         * @return R hash value
+         */					
         hashit: function(sha, n, B) {
             var R = [],
                 H, W, i, len;
@@ -188,8 +237,14 @@
             return W;
         },
 
-        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-        /* maps a random u to a point on the curve */
+	/**
+         * maps a random u to a point on the curve 
+         *
+         * @this {MPIN}
+         * @param u BIG numberInteger
+         * @param cb an integer representing the "sign" of y, in fact its least significant bit.
+         * @return P ECP pointhash value
+         */					
         map: function(u, cb) {
             var P = new ctx.ECP(),
                 x = new ctx.BIG(u),
@@ -210,7 +265,14 @@
             return P;
         },
 
-        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	/**
+         * returns u derived from P. Random value in range 1 to return value should then be added to u 
+         *
+         * @this {MPIN}
+         * @param u BIG numberInteger
+         * @param P ECP pointhash value
+         * @return r Value that should be added to u to derive P 
+         */							
         unmap: function(u, P) {
             var s = P.getS(),
                 R = new ctx.ECP(),
@@ -325,7 +387,15 @@
             return 0;
         },
 
-        /* R=R1+R2 in group G1 */
+	/**
+         * Add two members from the group G1
+         *
+         * @this {MPIN}
+         * @param R1 Input member of G1
+         * @param R2 Input member of G1
+         * @param R Output member of G1. R=R1+R2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G1: function(R1, R2, R) {
             var P = ctx.ECP.fromBytes(R1),
                 Q = ctx.ECP.fromBytes(R2);
@@ -341,7 +411,15 @@
             return 0;
         },
 
-        /* W=W1+W2 in group G2 */
+	/**
+         * Add two members from the group G2
+         *
+         * @this {MPIN}
+         * @param W1 Input member of G2
+         * @param W2 Input member of G2
+         * @param W Output member of G2. W=W1+W2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G2: function(W1, W2, W) {
             var P = ctx.ECP2.fromBytes(W1),
                 Q = ctx.ECP2.fromBytes(W2);
@@ -357,11 +435,26 @@
             return 0;
         },
 
+	/**
+         * Hash the identity
+         *
+         * @this {MPIN}
+         * @param sha is the hash type
+         * @param ID Identity as byte array
+         * @return hash value
+         */						
         HASH_ID: function(sha, ID) {
             return this.hashit(sha, 0, ID);
         },
 
-        /* create random secret S */
+	/**
+         * Create random secret
+         *
+         * @this {MPIN}
+         * @param rng cryptographically secure random number generator
+         * @param S Random secret value
+         * @return O for success or else error code
+         */					
         RANDOM_GENERATE: function(rng, S) {
             var r = new ctx.BIG(0),
                 s;
@@ -374,12 +467,31 @@
             return 0;
         },
 
-        /* Extract PIN from TOKEN for identity CID */
+	/**
+         * Extract a PIN number from a client secret
+         *
+         * @this {MPIN}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter pin PIN value
+         * @parameter TOKEN Client secret
+         * @return token
+         */					
         EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
             return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
         },
 
-        /* Extract factor from TOKEN for identity CID */
+	/**
+         * Extract factor from TOKEN for identity CID 
+         *
+         * @this {MPIN}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -400,7 +512,17 @@
             return 0;
         },
 
-        /* Restore factor to TOKEN for identity CID */
+	/**
+         * Restore factor to TOKEN for identity CID 
+         *
+         * @this {MPIN}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -421,7 +543,14 @@
             return 0;
         },
 
-        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	/**
+         * Create a server secret in G2 from a master secret
+         *
+         * @this {MPIN}
+         * @param S Master secret
+         * @param SST Server secret = s.Q where Q is a fixed generator of G2
+         * @return O for success or else error code
+         */					
         GET_SERVER_SECRET: function(S, SST) {
             var s,Q;
 
@@ -434,12 +563,17 @@
             return 0;
         },
 
-        /*
-         W=x*H(G);
-         if RNG == NULL then X is passed in
-         if RNG != NULL the X is passed out
-         if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-        */
+	/**
+         * Find a random multiple of a point in G1
+         *
+         * @this {MPIN}
+         * @parameter rng cryptographically secure random number generator
+	 * @param type determines type of action to be taken
+	 * @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param G if type=0 a point in G1, else an octet to be mapped to G1
+	 * @param W the output =x.G or x.M(G), where M(.) is a mapping
+         * @return O for success or else error code
+         */					
         GET_G1_MULTIPLE: function(rng, type, X, G, W) {
             var r = new ctx.BIG(0),
                 x, P;
@@ -468,12 +602,30 @@
         },
 
 
-        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+	/**
+         * Create a client secret in G1 from a master secret and the client ID
+         *
+         * @this {MPIN}
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CST is the full client secret = s.H(ID)
+         * @return O for success or else error code
+         */					
         GET_CLIENT_SECRET: function(S, CID, CST) {
             return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
         },
 
-        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	/**
+         * Create a Time Permit in G1 from a master secret and the client ID
+         *
+         * @this {MPIN}
+  	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch.
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CTT is a Time Permit for the given date = s.H(d|H(ID))
+         * @return O for success or else error code
+         */					
         GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
             var h = this.hashit(sha, date, CID),
                 P = ctx.ECP.mapit(h),
@@ -485,7 +637,23 @@
             return 0;
         },
 
-        /* Implement step 1 on client side of MPin protocol */
+	/**
+         * Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+         * @return O for success or else error code
+         */					
         CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
             var r = new ctx.BIG(0),
                 x, P, T, W, h;
@@ -545,7 +713,15 @@
             return 0;
         },
 
-        /* Implement step 2 on client side of MPin protocol */
+	/**
+         * Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+	 * @param X an input, a locally generated random number
+	 * @param Y an input random challenge from the server
+	 * @param SEC on output = -(x+y).V
+         * @return O for success or else error code
+         */					
         CLIENT_2: function(X, Y, SEC) {
             var r = new ctx.BIG(0),
                 P, px, py;
@@ -568,7 +744,17 @@
             return 0;
         },
 
-        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	/**
+         * Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CID is the input claimed client identity
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+         * @return O for success or else error code
+         */
         SERVER_1: function(sha, date, CID, HID, HTID) {
             var h = this.hashit(sha, 0, CID),
                 P = ctx.ECP.mapit(h),
@@ -583,7 +769,23 @@
             }
         },
 
-        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+	/**
+         * Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is input H(ID), a hash of the client ID
+	 * @param HTID is input H(ID)+H(d|H(ID))
+	 * @param Y is the input server's randomly generated challenge
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+         * @return O for success or else error code
+         */
         SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
             var Q, sQ, R, y, P, g;
 
@@ -669,7 +871,14 @@
             return 0;
         },
 
-        /* Pollards kangaroos used to return PIN error */
+	/**
+         * Use Kangaroos to find PIN error
+         *
+         * @this {MPIN}
+	 * @param E a member of the group GT
+	 * @param F a member of the group GT =  E^e
+	 * @return 0 if Kangaroos failed, or the PIN error e
+         */
         KANGAROO: function(E, F) {
             var ge = ctx.FP12.fromBytes(E),
                 gf = ctx.FP12.fromBytes(F),
@@ -722,13 +931,27 @@
             return res;
         },
 
-        /* return time  since epoch */
+	/**
+         * Time since epoch 
+         *
+         * @this {MPIN}
+	 * @return time since epoch 
+         */
         GET_TIME: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (1000));
         },
 
-        /* y = H(time,xCID) */
+	/**
+         * Generate Y=H(s,O), where s is epoch time, O is a byte array, and H(.) is a hash function
+         *
+         * @this {MPIN}
+  	 * @param sha is the hash type
+	 * @param TimeValue is epoch time in seconds
+	 * @param xCID input bytearray is an input octet
+	 * @param Y output value
+         * @return O for success or else error code
+         */
         GET_Y: function(sha, TimeValue, xCID, Y) {
             var q = new ctx.BIG(0),
                 h = this.hashit(sha, TimeValue, xCID),
@@ -742,7 +965,26 @@
             return 0;
         },
 
-        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+	/**
+         * Perform client side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param Message is the message to be signed
+         * @return O for success or else error code
+         */
         CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
             var rtn = 0,
                 M = [],
@@ -778,7 +1020,27 @@
             return 0;
         },
 
-        /* One pass MPIN Server */
+	/**
+         * Perform server side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param CID is the input claimed client identity
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param MESSAGE is the message to be signed
+	 * @param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+         * @return O for success or else error code
+         */
         SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
             var rtn = 0,
                 M = [],
@@ -810,7 +1072,16 @@
             return 0;
         },
 
-        /* Functions to support M-Pin Full */
+	/**
+         * Precompute values for use by the client side of M-Pin Full
+         *
+         * @this {MPIN}
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param CID is the input client identity
+	 * @param G1 precomputed output
+	 * @param G2 precomputed output
+         * @return O for success or else error code
+         */
         PRECOMPUTE: function(TOKEN, CID, G1, G2) {
             var P, T, g, Q;
 
@@ -833,8 +1104,20 @@
             return 0;
         },
 
-        /* Hash the M-Pin transcript - new */
-
+	/**
+         * Hash the session transcript
+         *
+         * @this {MPIN}
+ 	 * @param sha is the hash type
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is the client output = x.H(ID)
+	 * @param xCID is the client output = x.(H(ID)+H(T|H(ID)))
+	 * @param SEC is the client part response
+	 * @param Y is the server challenge
+	 * @param R is the client part response
+	 * @param W is the server part response
+	 * @return H the output is the hash of all of the above that apply
+         */
         HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
             var tlen = 0,
                 T = [],
@@ -880,8 +1163,21 @@
             return this.hashit(sha, 0, T);
         },
 
-        /* calculate common key on client side */
-        /* wCID = w.(A+AT) */
+	/**
+         * Calculate Key on Client side for M-Pin Full
+         *
+         * @this {MPIN}
+  	 * @param sha is the hash type
+	 * @param G1 precomputed input
+	 * @param G2 precomputed input
+	 * @param pin is the input PIN number
+	 * @param R is an input, a locally generated random number
+	 * @param X is an input, a locally generated random number
+	 * @param H is an input, hash of the protocol transcript
+	 * @param wCID is the input Server-side Diffie-Hellman component
+	 * @param CK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
             var t = [],
                 g1 = ctx.FP12.fromBytes(G1),
@@ -918,9 +1214,21 @@
             return 0;
         },
 
-        /* calculate common key on server side */
-        /* Z=r.A - no time permits involved */
-
+	/**
+         * Calculate Key on Server side for M-Pin Full
+         *
+         * @this {MPIN}
+ 	 * @param h is the hash type
+	 * @param Z is the input Client-side Diffie-Hellman component
+	 * @param SST is the input server secret
+	 * @param W is an input random number generated by the server
+	 * @param H is an input, hash of the protocol transcript
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param SK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
             var t = [],
                 sQ, R, A, U, w, h, g, c, i;
@@ -971,12 +1279,15 @@
             return 0;
         },
 
-        /* Generate a public key and the corresponding z for the key-escrow less scheme */
-        /*
-            if R==NULL then Z is passed in
-            if R!=NULL then Z is passed out
-            Pa=(z^-1).Q
-        */
+	/**
+         * Generates a random public key for the client z.Q
+         *
+         * @this {MPIN}
+         * @param rng cryptographically secure random number generator
+	 * @param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	 * @param Pa the output public key for the client
+	 * @return 0 or an error code
+         */	
         GET_DVS_KEYPAIR: function(rng, Z, Pa) {
             var r = new ctx.BIG(0),
                 z, Q;
diff --git a/src/mpin192.js b/src/mpin192.js
index c198a46..b8b4f2e 100644
--- a/src/mpin192.js
+++ b/src/mpin192.js
@@ -22,6 +22,12 @@
 var MPIN192 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of MPIN192
+      *
+      * @constructor
+      * @this {MPIN192}
+      */        
     var MPIN192 = {
         BAD_PARAMS: -11,
         INVALID_POINT: -14,
@@ -43,12 +49,24 @@
         SHA384: 48,
         SHA512: 64,
 
-        /* return time in slots since epoch */
+	/**
+         * Get epoch time
+         *
+         * @this {MPIN192}
+         * @return time in slots since epoch 
+         */	
         today: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
         },
 
+	/**
+         * Convert byte array to string
+         *
+         * @this {MPIN192}
+         * @param b byte array
+         * @return s string
+         */		
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -64,6 +82,13 @@
             return s;
         },
 
+	/**
+         * Convert a string to byte array
+         *
+         * @this {MPIN192}
+         * @param s string
+         * @return b byte array
+         */			
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -75,6 +100,14 @@
             return b;
         },
 
+	/**
+         * Convert byte arrays
+         *
+         * @this {MPIN192}
+         * @param a byte array
+         * @param b byte array
+         * @return true if equal
+         */				
         comparebytes: function(a, b) {
             if (a.length != b.length) {
                 return false;
@@ -89,6 +122,14 @@
             return true;
         },
 
+	/**
+         * Hash values
+         *
+         * @this {MPIN192}
+         * @param c FP8 instance
+         * @param U ECP unstancebyte array
+         * @return R hash value
+         */					
         mpin_hash: function(sha, c, U) {
             var t = [],
                 w = [],
@@ -162,7 +203,15 @@
             return R;
         },
 
-        /* Hash number (optional) and string to point on curve */
+	/**
+         * General purpose hash function
+         *
+         * @this {MPIN192}
+         * @param sha is the hash type
+         * @param n Integer
+         * @param B byte array
+         * @return R hash value
+         */					
         hashit: function(sha, n, B) {
             var R = [],
                 H, W, i, len;
@@ -206,8 +255,14 @@
             return W;
         },
 
-        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-        /* maps a random u to a point on the curve */
+	/**
+         * maps a random u to a point on the curve 
+         *
+         * @this {MPIN192}
+         * @param u BIG numberInteger
+         * @param cb an integer representing the "sign" of y, in fact its least significant bit.
+         * @return P ECP pointhash value
+         */					
         map: function(u, cb) {
             var P = new ctx.ECP(),
                 x = new ctx.BIG(u),
@@ -228,7 +283,14 @@
             return P;
         },
 
-        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	/**
+         * returns u derived from P. Random value in range 1 to return value should then be added to u 
+         *
+         * @this {MPIN192}
+         * @param u BIG numberInteger
+         * @param P ECP pointhash value
+         * @return r Value that should be added to u to derive P 
+         */						
         unmap: function(u, P) {
             var s = P.getS(),
                 R = new ctx.ECP(),
@@ -343,7 +405,15 @@
             return 0;
         },
 
-        /* R=R1+R2 in group G1 */
+	/**
+         * Add two members from the group G1
+         *
+         * @this {MPIN192}
+         * @param R1 Input member of G1
+         * @param R2 Input member of G1
+         * @param R Output member of G1. R=R1+R2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G1: function(R1, R2, R) {
             var P = ctx.ECP.fromBytes(R1),
                 Q = ctx.ECP.fromBytes(R2);
@@ -359,7 +429,15 @@
             return 0;
         },
 
-        /* W=W1+W2 in group G2 */
+	/**
+         * Add two members from the group G2
+         *
+         * @this {MPIN192}
+         * @param W1 Input member of G2
+         * @param W2 Input member of G2
+         * @param W Output member of G2. W=W1+W2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G2: function(W1, W2, W) {
             var P = ctx.ECP4.fromBytes(W1),
                 Q = ctx.ECP4.fromBytes(W2);
@@ -375,11 +453,26 @@
             return 0;
         },
 
+	/**
+         * Hash the identity
+         *
+         * @this {MPIN192}
+         * @param sha is the hash type
+         * @param ID Identity as byte array
+         * @return hash value
+         */					
         HASH_ID: function(sha, ID) {
             return this.hashit(sha, 0, ID);
         },
 
-        /* create random secret S */
+	/**
+         * Create random secret
+         *
+         * @this {MPIN192}
+         * @param rng cryptographically secure random number generator
+         * @param S Random secret value
+         * @return O for success or else error code
+         */					
         RANDOM_GENERATE: function(rng, S) {
             var r = new ctx.BIG(0),
                 s;
@@ -392,12 +485,31 @@
             return 0;
         },
 
-        /* Extract PIN from TOKEN for identity CID */
+	/**
+         * Extract a PIN number from a client secret
+         *
+         * @this {MPIN192}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter pin PIN value
+         * @parameter TOKEN Client secret
+         * @return token
+         */					
         EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
             return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
         },
 
-        /* Extract factor from TOKEN for identity CID */
+	/**
+         * Extract factor from TOKEN for identity CID 
+         *
+         * @this {MPIN192}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -418,7 +530,17 @@
             return 0;
         },
 
-        /* Restore factor to TOKEN for identity CID */
+	/**
+         * Restore factor to TOKEN for identity CID 
+         *
+         * @this {MPIN192}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -439,7 +561,14 @@
             return 0;
         },
 
-        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	/**
+         * Create a server secret in G2 from a master secret
+         *
+         * @this {MPIN192}
+         * @param S Master secret
+         * @param SST Server secret = s.Q where Q is a fixed generator of G2
+         * @return O for success or else error code
+         */					
         GET_SERVER_SECRET: function(S, SST) {
             var s,Q;
 
@@ -452,12 +581,17 @@
             return 0;
         },
 
-        /*
-         W=x*H(G);
-         if RNG == NULL then X is passed in
-         if RNG != NULL the X is passed out
-         if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-        */
+	/**
+         * Find a random multiple of a point in G1
+         *
+         * @this {MPIN192}
+         * @parameter rng cryptographically secure random number generator
+	 * @param type determines type of action to be taken
+	 * @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param G if type=0 a point in G1, else an octet to be mapped to G1
+	 * @param W the output =x.G or x.M(G), where M(.) is a mapping
+         * @return O for success or else error code
+         */					
         GET_G1_MULTIPLE: function(rng, type, X, G, W) {
             var r = new ctx.BIG(0),
                 x, P;
@@ -486,12 +620,30 @@
         },
 
 
-        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+	/**
+         * Create a client secret in G1 from a master secret and the client ID
+         *
+         * @this {MPIN192}
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CST is the full client secret = s.H(ID)
+         * @return O for success or else error code
+         */					
         GET_CLIENT_SECRET: function(S, CID, CST) {
             return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
         },
 
-        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	/**
+         * Create a Time Permit in G1 from a master secret and the client ID
+         *
+         * @this {MPIN192}
+  	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch.
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CTT is a Time Permit for the given date = s.H(d|H(ID))
+         * @return O for success or else error code
+         */					
         GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
             var h = this.hashit(sha, date, CID),
                 P = ctx.ECP.mapit(h),
@@ -503,7 +655,23 @@
             return 0;
         },
 
-        /* Implement step 1 on client side of MPin protocol */
+	/**
+         * Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+         * @return O for success or else error code
+         */					
         CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
             var r = new ctx.BIG(0),
                 x, P, T, W, h;
@@ -563,7 +731,15 @@
             return 0;
         },
 
-        /* Implement step 2 on client side of MPin protocol */
+	/**
+         * Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+	 * @param X an input, a locally generated random number
+	 * @param Y an input random challenge from the server
+	 * @param SEC on output = -(x+y).V
+         * @return O for success or else error code
+         */					
         CLIENT_2: function(X, Y, SEC) {
             var r = new ctx.BIG(0),
                 P, px, py;
@@ -587,7 +763,17 @@
             return 0;
         },
 
-        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	/**
+         * Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CID is the input claimed client identity
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+         * @return O for success or else error code
+         */
         SERVER_1: function(sha, date, CID, HID, HTID) {
             var h = this.hashit(sha, 0, CID),
                 P = ctx.ECP.mapit(h),
@@ -602,7 +788,23 @@
             }
         },
 
-        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+	/**
+         * Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is input H(ID), a hash of the client ID
+	 * @param HTID is input H(ID)+H(d|H(ID))
+	 * @param Y is the input server's randomly generated challenge
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+         * @return O for success or else error code
+         */
         SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
             var Q, sQ, R, y, P, g;
 
@@ -690,7 +892,14 @@
             return 0;
         },
 
-        /* Pollards kangaroos used to return PIN error */
+	/**
+         * Use Kangaroos to find PIN error
+         *
+         * @this {MPIN192}
+	 * @param E a member of the group GT
+	 * @param F a member of the group GT =  E^e
+	 * @return 0 if Kangaroos failed, or the PIN error e
+         */
         KANGAROO: function(E, F) {
             var ge = ctx.FP24.fromBytes(E),
                 gf = ctx.FP24.fromBytes(F),
@@ -743,13 +952,27 @@
             return res;
         },
 
-        /* return time  since epoch */
+	/**
+         * Time since epoch 
+         *
+         * @this {MPIN192}
+	 * @return time since epoch 
+         */
         GET_TIME: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (1000));
         },
 
-        /* y = H(time,xCID) */
+	/**
+         * Generate Y=H(s,O), where s is epoch time, O is a byte array, and H(.) is a hash function
+         *
+         * @this {MPIN192}
+  	 * @param sha is the hash type
+	 * @param TimeValue is epoch time in seconds
+	 * @param xCID input bytearray is an input octet
+	 * @param Y output value
+         * @return O for success or else error code
+         */
         GET_Y: function(sha, TimeValue, xCID, Y) {
             var q = new ctx.BIG(0),
                 h = this.hashit(sha, TimeValue, xCID),
@@ -763,7 +986,26 @@
             return 0;
         },
 
-        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+	/**
+         * Perform client side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param Message is the message to be signed
+         * @return O for success or else error code
+         */
         CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
             var rtn = 0,
                 M = [],
@@ -799,7 +1041,27 @@
             return 0;
         },
 
-        /* One pass MPIN Server */
+	/**
+         * Perform server side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN192}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param CID is the input claimed client identity
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param MESSAGE is the message to be signed
+	 * @param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+         * @return O for success or else error code
+         */
         SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
             var rtn = 0,
                 M = [],
@@ -831,7 +1093,16 @@
             return 0;
         },
 
-        /* Functions to support M-Pin Full */
+	/**
+         * Precompute values for use by the client side of M-Pin Full
+         *
+         * @this {MPIN192}
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param CID is the input client identity
+	 * @param G1 precomputed output
+	 * @param G2 precomputed output
+         * @return O for success or else error code
+         */
         PRECOMPUTE: function(TOKEN, CID, G1, G2) {
             var P, T, g, Q;
 
@@ -854,8 +1125,20 @@
             return 0;
         },
 
-        /* Hash the M-Pin transcript - new */
-
+	/**
+         * Hash the session transcript
+         *
+         * @this {MPIN192}
+ 	 * @param sha is the hash type
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is the client output = x.H(ID)
+	 * @param xCID is the client output = x.(H(ID)+H(T|H(ID)))
+	 * @param SEC is the client part response
+	 * @param Y is the server challenge
+	 * @param R is the client part response
+	 * @param W is the server part response
+	 * @return H the output is the hash of all of the above that apply
+         */
         HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
             var tlen = 0,
                 T = [],
@@ -901,8 +1184,21 @@
             return this.hashit(sha, 0, T);
         },
 
-        /* calculate common key on client side */
-        /* wCID = w.(A+AT) */
+	/**
+         * Calculate Key on Client side for M-Pin Full
+         *
+         * @this {MPIN192}
+  	 * @param sha is the hash type
+	 * @param G1 precomputed input
+	 * @param G2 precomputed input
+	 * @param pin is the input PIN number
+	 * @param R is an input, a locally generated random number
+	 * @param X is an input, a locally generated random number
+	 * @param H is an input, hash of the protocol transcript
+	 * @param wCID is the input Server-side Diffie-Hellman component
+	 * @param CK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
             var t = [],
                 g1 = ctx.FP24.fromBytes(G1),
@@ -939,9 +1235,21 @@
             return 0;
         },
 
-        /* calculate common key on server side */
-        /* Z=r.A - no time permits involved */
-
+	/**
+         * Calculate Key on Server side for M-Pin Full
+         *
+         * @this {MPIN192}
+ 	 * @param h is the hash type
+	 * @param Z is the input Client-side Diffie-Hellman component
+	 * @param SST is the input server secret
+	 * @param W is an input random number generated by the server
+	 * @param H is an input, hash of the protocol transcript
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param SK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
             var t = [],
                 sQ, R, A, U, w, h, g, c, i;
@@ -991,6 +1299,15 @@
             return 0;
         },
 
+	/**
+         * Generates a random public key for the client z.Q
+         *
+         * @this {MPIN192}
+         * @param rng cryptographically secure random number generator
+	 * @param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	 * @param Pa the output public key for the client
+	 * @return 0 or an error code
+         */
         GET_DVS_KEYPAIR: function(rng, Z, Pa) {
             var r = new ctx.BIG(0),
                 z, Q;
diff --git a/src/mpin256.js b/src/mpin256.js
index bf985f7..326fbfc 100644
--- a/src/mpin256.js
+++ b/src/mpin256.js
@@ -22,6 +22,12 @@
 var MPIN256 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of MPIN256
+      *
+      * @constructor
+      * @this {MPIN256}
+      */        
     var MPIN256 = {
         BAD_PARAMS: -11,
         INVALID_POINT: -14,
@@ -43,12 +49,24 @@
         SHA384: 48,
         SHA512: 64,
 
-        /* return time in slots since epoch */
+	/**
+         * Get epoch time for day
+         *
+         * @this {MPIN256}
+         * @return time in slots since epoch 
+         */	
         today: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (60000 * 1440)); // for daily tokens
         },
 
+	/**
+         * Convert byte array to string
+         *
+         * @this {MPIN256}
+         * @param b byte array
+         * @return s string
+         */			
         bytestostring: function(b) {
             var s = "",
                 len = b.length,
@@ -64,6 +82,13 @@
             return s;
         },
 
+	/**
+         * Convert a string to byte array
+         *
+         * @this {MPIN256}
+         * @param s string
+         * @return b byte array
+         */				
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -75,6 +100,14 @@
             return b;
         },
 
+	/**
+         * Convert byte arrays
+         *
+         * @this {MPIN256}
+         * @param a byte array
+         * @param b byte array
+         * @return true if equal
+         */				
         comparebytes: function(a, b) {
             if (a.length != b.length) {
                 return false;
@@ -89,6 +122,14 @@
             return true;
         },
 
+	/**
+         * Hash values
+         *
+         * @this {MPIN256}
+         * @param c FP8 instance
+         * @param U ECP unstancebyte array
+         * @return R hash value
+         */						
         mpin_hash: function(sha, c, U) {
             var t = [],
                 w = [],
@@ -196,7 +237,15 @@
             return R;
         },
 
-        /* Hash number (optional) and string to point on curve */
+	/**
+         * General purpose hash function
+         *
+         * @this {MPIN256}
+         * @param sha is the hash type
+         * @param n Integer
+         * @param B byte array
+         * @return R hash value
+         */					
         hashit: function(sha, n, B) {
             var R = [],
                 H, W, i, len;
@@ -240,8 +289,14 @@
             return W;
         },
 
-        /* these next two functions help to implement elligator squared - http://eprint.iacr.org/2014/043 */
-        /* maps a random u to a point on the curve */
+	/**
+         * maps a random u to a point on the curve 
+         *
+         * @this {MPIN256}
+         * @param u BIG numberInteger
+         * @param cb an integer representing the "sign" of y, in fact its least significant bit.
+         * @return P ECP pointhash value
+         */					
         map: function(u, cb) {
             var P = new ctx.ECP(),
                 x = new ctx.BIG(u),
@@ -262,7 +317,14 @@
             return P;
         },
 
-        /* returns u derived from P. Random value in range 1 to return value should then be added to u */
+	/**
+         * returns u derived from P. Random value in range 1 to return value should then be added to u 
+         *
+         * @this {MPIN256}
+         * @param u BIG numberInteger
+         * @param P ECP pointhash value
+         * @return r Value that should be added to u to derive P 
+         */						
         unmap: function(u, P) {
             var s = P.getS(),
                 R = new ctx.ECP(),
@@ -377,7 +439,15 @@
             return 0;
         },
 
-        /* R=R1+R2 in group G1 */
+	/**
+         * Add two members from the group G1
+         *
+         * @this {MPIN256}
+         * @param R1 Input member of G1
+         * @param R2 Input member of G1
+         * @param R Output member of G1. R=R1+R2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G1: function(R1, R2, R) {
             var P = ctx.ECP.fromBytes(R1),
                 Q = ctx.ECP.fromBytes(R2);
@@ -393,7 +463,15 @@
             return 0;
         },
 
-        /* W=W1+W2 in group G2 */
+	/**
+         * Add two members from the group G2
+         *
+         * @this {MPIN256}
+         * @param W1 Input member of G2
+         * @param W2 Input member of G2
+         * @param W Output member of G2. W=W1+W2
+         * @return 0 or an error code
+         */						
         RECOMBINE_G2: function(W1, W2, W) {
             var P = ctx.ECP8.fromBytes(W1),
                 Q = ctx.ECP8.fromBytes(W2);
@@ -409,11 +487,26 @@
             return 0;
         },
 
+	/**
+         * Hash the identity
+         *
+         * @this {MPIN256}
+         * @param sha is the hash type
+         * @param ID Identity as byte array
+         * @return hash value
+         */					
         HASH_ID: function(sha, ID) {
             return this.hashit(sha, 0, ID);
         },
 
-        /* create random secret S */
+	/**
+         * Create random secret
+         *
+         * @this {MPIN256}
+         * @param rng cryptographically secure random number generator
+         * @param S Random secret value
+         * @return O for success or else error code
+         */					
         RANDOM_GENERATE: function(rng, S) {
             var r = new ctx.BIG(0),
                 s;
@@ -426,12 +519,31 @@
             return 0;
         },
 
-        /* Extract PIN from TOKEN for identity CID */
+	/**
+         * Extract a PIN number from a client secret
+         *
+         * @this {MPIN256}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter pin PIN value
+         * @parameter TOKEN Client secret
+         * @return token
+         */					
         EXTRACT_PIN: function(sha, CID, pin, TOKEN) {
             return this.EXTRACT_FACTOR(sha,CID,pin%this.MAXPIN,this.PBLEN,TOKEN);
         },
 
-        /* Extract factor from TOKEN for identity CID */
+	/**
+         * Extract factor from TOKEN for identity CID 
+         *
+         * @this {MPIN256}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         EXTRACT_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -452,7 +564,17 @@
             return 0;
         },
 
-        /* Restore factor to TOKEN for identity CID */
+	/**
+         * Restore factor to TOKEN for identity CID 
+         *
+         * @this {MPIN256}
+         * @parameter sha hash type
+         * @parameter CID Client identity
+         * @parameter factor Value to extract
+         * @parameter facbits Number of bits in factor
+         * @parameter TOKEN Token value
+         * @return token
+         */					
         RESTORE_FACTOR: function(sha, CID, factor, facbits, TOKEN) {
             var P, R, h;
 
@@ -473,7 +595,14 @@
             return 0;
         },
 
-        /* Extract Server Secret SST=S*Q where Q is fixed generator in G2 and S is master secret */
+	/**
+         * Create a server secret in G2 from a master secret
+         *
+         * @this {MPIN256}
+         * @param S Master secret
+         * @param SST Server secret = s.Q where Q is a fixed generator of G2
+         * @return O for success or else error code
+         */					
         GET_SERVER_SECRET: function(S, SST) {
             var s,Q;
 
@@ -486,12 +615,17 @@
             return 0;
         },
 
-        /*
-         * W=x*H(G);
-         * if RNG == NULL then X is passed in
-         * if RNG != NULL the X is passed out
-         * if type=0 W=x*G where G is point on the curve, else W=x*M(G), where M(G) is mapping of octet G to point on the curve
-        */
+	/**
+         * Find a random multiple of a point in G1
+         *
+         * @this {MPIN256}
+         * @parameter rng cryptographically secure random number generator
+	 * @param type determines type of action to be taken
+	 * @param x an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param G if type=0 a point in G1, else an octet to be mapped to G1
+	 * @param W the output =x.G or x.M(G), where M(.) is a mapping
+         * @return O for success or else error code
+         */					
         GET_G1_MULTIPLE: function(rng, type, X, G, W) {
             var r = new ctx.BIG(0),
                 x, P;
@@ -520,12 +654,30 @@
         },
 
 
-        /* Client secret CST=S*H(CID) where CID is client ID and S is master secret */
+	/**
+         * Create a client secret in G1 from a master secret and the client ID
+         *
+         * @this {MPIN256}
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CST is the full client secret = s.H(ID)
+         * @return O for success or else error code
+         */					
         GET_CLIENT_SECRET: function(S, CID, CST) {
             return this.GET_G1_MULTIPLE(null, 1, S, CID, CST);
         },
 
-        /* Time Permit CTT=S*(date|H(CID)) where S is master secret */
+	/**
+         * Create a Time Permit in G1 from a master secret and the client ID
+         *
+         * @this {MPIN256}
+  	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch.
+	 * @param S is an input master secret
+	 * @param CID is the input client identity
+	 * @param CTT is a Time Permit for the given date = s.H(d|H(ID))
+         * @return O for success or else error code
+         */					
         GET_CLIENT_PERMIT: function(sha, date, S, CID, CTT) {
             var h = this.hashit(sha, date, CID),
                 P = ctx.ECP.mapit(h),
@@ -537,7 +689,23 @@
             return 0;
         },
 
-        /* Implement step 1 on client side of MPin protocol */
+	/**
+         * Perform first pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = CS+TP, where CS=is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+         * @return O for success or else error code
+         */					
         CLIENT_1: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT) {
             var r = new ctx.BIG(0),
                 x, P, T, W, h;
@@ -598,7 +766,15 @@
             return 0;
         },
 
-        /* Implement step 2 on client side of MPin protocol */
+	/**
+         * Perform second pass of the client side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+	 * @param X an input, a locally generated random number
+	 * @param Y an input random challenge from the server
+	 * @param SEC on output = -(x+y).V
+         * @return O for success or else error code
+         */					
         CLIENT_2: function(X, Y, SEC) {
             var r = new ctx.BIG(0),
                 P, px, py;
@@ -622,7 +798,17 @@
             return 0;
         },
 
-        /* Outputs H(CID) and H(T|H(CID)) for time permits. If no time permits set HID=HTID */
+	/**
+         * Perform first pass of the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CID is the input claimed client identity
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+         * @return O for success or else error code
+         */
         SERVER_1: function(sha, date, CID, HID, HTID) {
             var h = this.hashit(sha, 0, CID),
                 P = ctx.ECP.mapit(h),
@@ -637,7 +823,23 @@
             }
         },
 
-        /* Implement step 1 of MPin protocol on server side. Pa is the client public key in case of DVS, otherwise must be set to null */
+	/**
+         * Perform third pass on the server side of the 3-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is input H(ID), a hash of the client ID
+	 * @param HTID is input H(ID)+H(d|H(ID))
+	 * @param Y is the input server's randomly generated challenge
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param Pa is the input public key from the client, z.Q or NULL if the client uses regular mpin
+         * @return O for success or else error code
+         */
         SERVER_2: function(date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, Pa) {
             var Q, sQ, R, y, P, g;
 
@@ -724,7 +926,14 @@
             return 0;
         },
 
-        /* Pollards kangaroos used to return PIN error */
+	/**
+         * Use Kangaroos to find PIN error
+         *
+         * @this {MPIN256}
+	 * @param E a member of the group GT
+	 * @param F a member of the group GT =  E^e
+	 * @return 0 if Kangaroos failed, or the PIN error e
+         */
         KANGAROO: function(E, F) {
             var ge = ctx.FP48.fromBytes(E),
                 gf = ctx.FP48.fromBytes(F),
@@ -777,7 +986,12 @@
             return res;
         },
 
-        /* return time  since epoch */
+	/**
+         * Time since epoch 
+         *
+         * @this {MPIN256}
+	 * @return time since epoch 
+         */
         GET_TIME: function() {
             var now = new Date();
             return Math.floor(now.getTime() / (1000));
@@ -797,7 +1011,26 @@
             return 0;
         },
 
-        /* One pass MPIN Client - DVS signature. Message must be null in case of One pass MPIN. */
+	/**
+         * Perform client side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param CLIENT_ID is the input client identity
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param X an output internally randomly generated if R!=NULL, otherwise must be provided as an input
+	 * @param pin is the input PIN number
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param SEC is output = -(x+y)(CS+TP), where CS is the reconstructed client secret, and TP is the time permit
+	 * @param xID is output = x.H(ID)
+	 * @param xCID is output = x.(H(ID)+H(d|H(ID)))
+	 * @param PERMIT is the input time permit
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param Message is the message to be signed
+         * @return O for success or else error code
+         */
         CLIENT: function(sha, date, CLIENT_ID, rng, X, pin, TOKEN, SEC, xID, xCID, PERMIT, TimeValue, Y, Message) {
             var rtn = 0,
                 M = [],
@@ -833,7 +1066,27 @@
             return 0;
         },
 
-        /* One pass MPIN Server */
+	/**
+         * Perform server side of the one-pass version of the M-Pin protocol
+         *
+         * @this {MPIN256}
+ 	 * @param sha is the hash type
+	 * @param date is input date, in days since the epoch. Set to 0 if Time permits disabled
+	 * @param HID is output H(ID), a hash of the client ID
+	 * @param HTID is output H(ID)+H(d|H(ID))
+	 * @param Y is output H(t|U) or H(t|UT) if Time Permits enabled
+	 * @param SST is the input server secret
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param mSEC is an input from the client
+	 * @param E is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param F is an output to help the Kangaroos to find the PIN error, or NULL if not required
+	 * @param CID is the input claimed client identity
+	 * @param TimeValue is input epoch time in seconds - a timestamp
+	 * @param MESSAGE is the message to be signed
+	 * @param Pa is input from the client z.Q or NULL if the key-escrow less scheme is not used
+         * @return O for success or else error code
+         */
         SERVER: function(sha, date, HID, HTID, Y, SST, xID, xCID, mSEC, E, F, CID, TimeValue, Message, Pa) {
             var rtn = 0,
                 M = [],
@@ -865,7 +1118,16 @@
             return 0;
         },
 
-        /* Functions to support M-Pin Full */
+	/**
+         * Precompute values for use by the client side of M-Pin Full
+         *
+         * @this {MPIN256}
+	 * @param TOKEN is the input M-Pin token (the client secret with PIN portion removed)
+	 * @param CID is the input client identity
+	 * @param G1 precomputed output
+	 * @param G2 precomputed output
+         * @return O for success or else error code
+         */
         PRECOMPUTE: function(TOKEN, CID, G1, G2) {
             var P, T, g, Q;
 
@@ -888,8 +1150,20 @@
             return 0;
         },
 
-        /* Hash the M-Pin transcript - new */
-
+	/**
+         * Hash the session transcript
+         *
+         * @this {MPIN256}
+ 	 * @param sha is the hash type
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is the client output = x.H(ID)
+	 * @param xCID is the client output = x.(H(ID)+H(T|H(ID)))
+	 * @param SEC is the client part response
+	 * @param Y is the server challenge
+	 * @param R is the client part response
+	 * @param W is the server part response
+	 * @return H the output is the hash of all of the above that apply
+         */
         HASH_ALL: function(sha, HID, xID, xCID, SEC, Y, R, W) {
             var tlen = 0,
                 T = [],
@@ -935,8 +1209,21 @@
             return this.hashit(sha, 0, T);
         },
 
-        /* calculate common key on client side */
-        /* wCID = w.(A+AT) */
+	/**
+         * Calculate Key on Client side for M-Pin Full
+         *
+         * @this {MPIN256}
+  	 * @param sha is the hash type
+	 * @param G1 precomputed input
+	 * @param G2 precomputed input
+	 * @param pin is the input PIN number
+	 * @param R is an input, a locally generated random number
+	 * @param X is an input, a locally generated random number
+	 * @param H is an input, hash of the protocol transcript
+	 * @param wCID is the input Server-side Diffie-Hellman component
+	 * @param CK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         CLIENT_KEY: function(sha, G1, G2, pin, R, X, H, wCID, CK) {
             var t = [],
                 g1 = ctx.FP48.fromBytes(G1),
@@ -972,9 +1259,21 @@
             return 0;
         },
 
-        /* calculate common key on server side */
-        /* Z=r.A - no time permits involved */
-
+	/**
+         * Calculate Key on Server side for M-Pin Full
+         *
+         * @this {MPIN256}
+ 	 * @param h is the hash type
+	 * @param Z is the input Client-side Diffie-Hellman component
+	 * @param SST is the input server secret
+	 * @param W is an input random number generated by the server
+	 * @param H is an input, hash of the protocol transcript
+	 * @param HID is the hashed input client ID = H(ID)
+	 * @param xID is input from the client = x.H(ID)
+	 * @param xCID is input from the client= x.(H(ID)+H(d|H(ID)))
+	 * @param SK is the output calculated shared key
+	 * @return 0 or an error code
+         */
         SERVER_KEY: function(sha, Z, SST, W, H, HID, xID, xCID, SK) {
             var t = [],
                 sQ, R, A, U, w, h, g, c, i;
@@ -1024,6 +1323,15 @@
             return 0;
         },
 
+	/**
+         * Generates a random public key for the client z.Q
+         *
+         * @this {MPIN256}
+         * @param rng cryptographically secure random number generator
+	 * @param Z an output internally randomly generated if R!=NULL, otherwise it must be provided as an input
+	 * @param Pa the output public key for the client
+	 * @return 0 or an error code
+         */	
         GET_DVS_KEYPAIR: function(rng, Z, Pa) {
             var r = new ctx.BIG(0),
                 z, Q;
diff --git a/src/pair.js b/src/pair.js
index bf009a7..3f58375 100644
--- a/src/pair.js
+++ b/src/pair.js
@@ -20,8 +20,19 @@
 var PAIR = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of PAIR
+      *
+      * @constructor
+      * @this {PAIR}
+      */                   
     var PAIR = {
-        /* Line function */
+	
+	/**
+         * Line function 
+         *
+         * @this {PAIR}
+         */	
         line: function(A, B, Qx, Qy) {
             var r = new ctx.FP12(1),
                 c = new ctx.FP4(0),
@@ -127,16 +138,26 @@
             return r;
         },
 
-		/* prepare for multi-pairing */
-		initmp: function() {
+	/**
+         * prepare for multi-pairing 
+         *
+         * @this {PAIR}
+         */	
+	initmp: function() {
 			var r=[];
 			for (var i=0;i<ctx.ECP.ATE_BITS;i++)
 				r[i] = new ctx.FP12(1);
 			return r;
 		},
 
-		/* basic Miller loop */
-		miller: function(r) {
+	/**
+         * basic Miller loop
+         *
+         * @this {PAIR}
+	 * @param r FP12 precomputed array of accumulated line functions
+ 	 * @param res FP12 result
+         */	
+	miller: function(r) {
 			var res=new ctx.FP12(1);
 			for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
 			{
@@ -151,8 +172,15 @@
 			return res;
 		},
 
-		/* Accumulate another set of line functions for n-pairing */
-		another: function(r,P1,Q1) {
+	/**
+         * Precompute line functions for n-pairing
+         *
+         * @this {PAIR}
+         * @param r array of precomputed FP48 products of line functions
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+         */
+	another: function(r,P1,Q1) {
 
 			var f;
 			var n=new ctx.BIG(0);
@@ -229,7 +257,14 @@
 			}	 
 		},
 
-        /* Optimal R-ate pairing */
+	/**
+         * Calculate Miller loop for Optimal ATE pairing e(P,Q)
+         *
+         * @this {PAIR}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @result r An element of GT i.e. result of the pairing calculation e(P,Q)
+         */
         ate: function(P1, Q1) {
             var fa, fb, f, x, n, n3, K, lv, lv2,
                 Qx, Qy, A, NP, r, nb, bt,
@@ -309,7 +344,16 @@
             return r;
         },
 
-        /* Optimal R-ate double pairing e(P,Q).e(R,S) */	
+	/**
+         * Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+         *
+         * @this {PAIR}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @param R1 An element of G2
+	 * @param S1 An element of G1
+	 * @result r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)
+         */
         ate2: function(P1, Q1, R1, S1) {
             var fa, fb, f, x, n, n3, K, lv, lv2,
                 Qx, Qy, Sx, Sy, A, B, NP,NR,r, nb, bt,
@@ -418,7 +462,13 @@
             return r;
         },
 
-        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	/**
+         * Final exponentiation of pairing, converts output of Miller loop to element in GT
+         *
+         * @this {PAIR}
+	 * @param m FP12 value
+	 * @result r m^((p^12-1)/r) where p is modulus and r is the group order
+         */
         fexp: function(m) {
             var fa, fb, f, x, r, lv,
                 x0, x1, x2, x3, x4, x5,
@@ -564,8 +614,12 @@
         }
     };
 
-	/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
-	PAIR.lbits = function(n3,n) {
+    /**
+      * prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n 
+      *
+      * @this {PAIR}
+      */
+    PAIR.lbits = function(n3,n) {
 		n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
 		if (ctx.ECP.CURVE_PAIRING_TYPE==ctx.ECP.BN)
 		{
@@ -585,7 +639,11 @@
 		return n3.nbits();
 	};
 
-    /* GLV method */
+    /**
+      * GLV method
+      *
+      * @this {PAIR}
+      */
     PAIR.glv = function(e) {
         var u = [],
             t, q, v, d, x, x2, i, j;
@@ -631,7 +689,11 @@
         return u;
     };
 
-    /* Galbraith & Scott Method */
+    /**
+      * Galbraith & Scott Method
+      *
+      * @this {PAIR}
+      */
     PAIR.gs = function(e) {
         var u = [],
             i, j, t, q, v, d, x, w;
@@ -684,7 +746,14 @@
         return u;
     };
 
-    /* Multiply P by e in group G1 */
+    /**
+      * Fast point multiplication of a member of the group G1 by a BIG number
+      *
+      * @this {PAIR}
+      * @param P Member of G1
+      * @param e BIG multiplier
+      * @return R Member of G1 R=e.P
+      */
     PAIR.G1mul = function(P, e) {
         var R, Q, q, bcru, cru, t, u, np, nn;
 
@@ -728,7 +797,14 @@
         return R;
     };
 
-    /* Multiply P by e in group G2 */
+    /**
+      * Multiply P by e in group G2
+      *
+      * @this {PAIR}
+      * @param P Member of G2
+      * @param e BIG multiplier
+      * @return R Member of G2 R=e.P
+      */
     PAIR.G2mul = function(P, e) {
         var R, Q, fa, fb, f, q, u, t, i, np, nn;
 
@@ -778,7 +854,14 @@
         return R;
     };
 
-    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    /**
+      * Fast raising of a member of GT to a BIG power
+      *
+      * @this {PAIR}
+      * @param d Member of GT
+      * @param e BIG exponent
+      * @return r d^e
+      */    
     PAIR.GTpow = function(d, e) {
         var r, g, fa, fb, f, q, t, u, i, np, nn;
 
diff --git a/src/pair192.js b/src/pair192.js
index b01ced3..5108cd1 100644
--- a/src/pair192.js
+++ b/src/pair192.js
@@ -20,8 +20,19 @@
 var PAIR192 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of PAIR192
+      *
+      * @constructor
+      * @this {PAIR192}
+      */            
     var PAIR192 = {
-        /* Line function */
+	
+	/**
+         * Line function 
+         *
+         * @this {PAIR192}
+         */	
         line: function(A, B, Qx, Qy) {
             var r = new ctx.FP24(1),
                 XX, YY, ZZ, YZ, sb,
@@ -125,16 +136,26 @@
             return r;
         },
 
-		/* prepare for multi-pairing */
-		initmp: function() {
+	/**
+         * prepare for multi-pairing 
+         *
+         * @this {PAIR192}
+         */	
+	initmp: function() {
 			var r=[];
 			for (var i=0;i<ctx.ECP.ATE_BITS;i++)
 				r[i] = new ctx.FP24(1);
 			return r;
 		},
 
-		/* basic Miller loop */
-		miller: function(r) {
+	/**
+         * basic Miller loop
+         *
+         * @this {PAIR192}
+	 * @param r FP24 precomputed array of accumulated line functions
+ 	 * @param res FP24 result
+         */	
+	miller: function(r) {
 			var res=new ctx.FP24(1);
 			for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
 			{
@@ -149,8 +170,15 @@
 			return res;
 		},
 
-		/* Accumulate another set of line functions for n-pairing */
-		another: function(r,P1,Q1) {
+	/**
+         * Precompute line functions for n-pairing
+         *
+         * @this {PAIR192}
+         * @param r array of precomputed FP24 products of line functions
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+         */
+	another: function(r,P1,Q1) {
 			var f;
 			var n=new ctx.BIG(0);
 			var n3=new ctx.BIG(0);
@@ -195,7 +223,14 @@
 		},
 
 
-        /* Optimal R-ate pairing */
+	/**
+         * Calculate Miller loop for Optimal ATE pairing e(P,Q)
+         *
+         * @this {PAIR192}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @result r An element of GT i.e. result of the pairing calculation e(P,Q)
+         */
         ate: function(P1, Q1) {
             var x, n, n3, lv, lv2,
                 Qx, Qy, A, NP, r, nb, bt,
@@ -244,7 +279,16 @@
             return r;
         },
 
-        /* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	/**
+         * Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+         *
+         * @this {PAIR192}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @param R1 An element of G2
+	 * @param S1 An element of G1
+	 * @result r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)
+         */
         ate2: function(P1, Q1, R1, S1) {
             var x, n, n3, lv, lv2,
                 Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
@@ -311,7 +355,13 @@
             return r;
         },
 
-        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	/**
+         * Final exponentiation of pairing, converts output of Miller loop to element in GT
+         *
+         * @this {PAIR192}
+	 * @param m FP24 value
+	 * @result r m^((p^12-1)/r) where p is modulus and r is the group order
+         */
         fexp: function(m) {
             var fa, fb, f, x, r, lv,
                 t0,t1,t2,t3,t4,t5,t6,t7;
@@ -414,7 +464,11 @@
         }
     };
 
-	/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
+	/**
+         * prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n 
+         *
+         * @this {PAIR192}
+         */
 	PAIR192.lbits = function(n3,n) {
 		n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
 		n3.copy(n);
@@ -423,7 +477,11 @@
 		return n3.nbits();
 	};
 
-    /* GLV method */
+    /**
+      * GLV method
+      *
+      * @this {PAIR192}
+      */
     PAIR192.glv = function(e) {
         var u = [],
             q, x, x2;
@@ -444,7 +502,11 @@
         return u;
     };
 
-    /* Galbraith & Scott Method */
+    /**
+      * Galbraith & Scott Method
+      *
+      * @this {PAIR192}
+      */
     PAIR192.gs = function(e) {
         var u = [],
             i, q, x, w;
@@ -472,7 +534,14 @@
         return u;
     };
 
-    /* Multiply P by e in group G1 */
+    /**
+      * Fast point multiplication of a member of the group G1 by a BIG number
+      *
+      * @this {PAIR192}
+      * @param P Member of G1
+      * @param e BIG multiplier
+      * @return R Member of G1 R=e.P
+      */
     PAIR192.G1mul = function(P, e) {
         var R, Q, q, bcru, cru, t, u, np, nn;
 
@@ -516,7 +585,14 @@
         return R;
     };
 
-    /* Multiply P by e in group G2 */
+    /**
+      * Multiply P by e in group G2
+      *
+      * @this {PAIR192}
+      * @param P Member of G2
+      * @param e BIG multiplier
+      * @return R Member of G2 R=e.P
+      */
     PAIR192.G2mul = function(P, e) {
         var R, Q, F, q, u, t, i, np, nn;
 
@@ -558,7 +634,14 @@
         return R;
     };
 
-    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    /**
+      * Fast raising of a member of GT to a BIG power
+      *
+      * @this {PAIR192}
+      * @param d Member of GT
+      * @param e BIG exponent
+      * @return r d^e
+      */    
     PAIR192.GTpow = function(d, e) {
         var r, g, fa, fb, f, q, t, u, i, np, nn;
 
diff --git a/src/pair256.js b/src/pair256.js
index b48126f..d8dfc5a 100644
--- a/src/pair256.js
+++ b/src/pair256.js
@@ -20,8 +20,19 @@
 var PAIR256 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of PAIR256
+      *
+      * @constructor
+      * @this {PAIR256}
+      */                
     var PAIR256 = {
-        /* Line function */
+	
+	/**
+         * Line function 
+         *
+         * @this {PAIR256}
+         */	
         line: function(A, B, Qx, Qy) {
             var r = new ctx.FP48(1),
                 XX, YY, ZZ, YZ, sb,
@@ -125,16 +136,26 @@
             return r;
         },
 
-		/* prepare for multi-pairing */
-		initmp: function() {
+	/**
+         * prepare for multi-pairing 
+         *
+         * @this {PAIR256}
+         */	
+	initmp: function() {
 			var r=[];
 			for (var i=0;i<ctx.ECP.ATE_BITS;i++)
 				r[i] = new ctx.FP48(1);
 			return r;
 		},
 
-		/* basic Miller loop */
-		miller: function(r) {
+	/**
+         * basic Miller loop
+         *
+         * @this {PAIR256}
+	 * @param r FP48 precomputed array of accumulated line functions
+ 	 * @param res FP48 result
+         */	
+	miller: function(r) {
 			var res=new ctx.FP48(1);
 			for (var i=ctx.ECP.ATE_BITS-1; i>=1; i--)
 			{
@@ -149,8 +170,15 @@
 			return res;
 		},
 
-		/* Accumulate another set of line functions for n-pairing */
-		another: function(r,P1,Q1) {
+	/**
+         * Precompute line functions for n-pairing
+         *
+         * @this {PAIR256}
+         * @param r array of precomputed FP48 products of line functions
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+         */
+	another: function(r,P1,Q1) {
 			var f;
 			var n=new ctx.BIG(0);
 			var n3=new ctx.BIG(0);
@@ -195,7 +223,14 @@
 		},
 
 
-        /* Optimal R-ate pairing */
+	/**
+         * Calculate Miller loop for Optimal ATE pairing e(P,Q)
+         *
+         * @this {PAIR256}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @result r An element of GT i.e. result of the pairing calculation e(P,Q)
+         */
         ate: function(P1, Q1) {
             var x, n, n3, lv, lv2,
                 Qx, Qy, A, NP, r, nb, bt,
@@ -244,7 +279,16 @@
             return r;
         },
 
-        /* Optimal R-ate double pairing e(P,Q).e(R,S) */
+	/**
+         * Calculate Miller loop for Optimal ATE double-pairing e(P,Q).e(R,S)
+         *
+         * @this {PAIR256}
+	 * @param P1 An element of G2
+	 * @param Q1 An element of G1
+	 * @param R1 An element of G2
+	 * @param S1 An element of G1
+	 * @result r An element of GT i.e. result of the double pairing calculation e(P,Q).e(R,S)
+         */
         ate2: function(P1, Q1, R1, S1) {
             var x, n, n3, lv, lv2,
                 Qx, Qy, Sx, Sy, A, B, NP, NR, r, nb, bt,
@@ -311,7 +355,13 @@
             return r;
         },
 
-        /* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */
+	/**
+         * Final exponentiation of pairing, converts output of Miller loop to element in GT
+         *
+         * @this {PAIR256}
+	 * @param m FP48 value
+	 * @result r m^((p^12-1)/r) where p is modulus and r is the group order
+         */
         fexp: function(m) {
             var fa, fb, f, x, r, lv,
                 t1,t2,t3,t7;
@@ -485,8 +535,12 @@
         }
     };
 
-	/* prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n */
-	PAIR256.lbits = function(n3,n) {
+    /**
+      * prepare ate parameter, n=6u+2 (BN) or n=u (BLS), n3=3*n 
+      *
+      * @this {PAIR256}
+      */
+    PAIR256.lbits = function(n3,n) {
 		n.rcopy(ctx.ROM_CURVE.CURVE_Bnx);
 		n3.copy(n);
 		n3.pmul(3);
@@ -494,7 +548,11 @@
 		return n3.nbits();
 	};
 
-    /* GLV method */
+    /**
+      * GLV method
+      *
+      * @this {PAIR256}
+      */
     PAIR256.glv = function(e) {
         var u = [],
             q, x, x2;
@@ -516,7 +574,11 @@
         return u;
     };
 
-    /* Galbraith & Scott Method */
+    /**
+      * Galbraith & Scott Method
+      *
+      * @this {PAIR256}
+      */
     PAIR256.gs = function(e) {
         var u = [],
             i, q, x, w;
@@ -549,7 +611,14 @@
         return u;
     };
 
-    /* Multiply P by e in group G1 */
+    /**
+      * Fast point multiplication of a member of the group G1 by a BIG number
+      *
+      * @this {PAIR256}
+      * @param P Member of G1
+      * @param e BIG multiplier
+      * @return R Member of G1 R=e.P
+      */
     PAIR256.G1mul = function(P, e) {
         var R, Q, q, bcru, cru, t, u, np, nn;
 
@@ -593,7 +662,14 @@
         return R;
     };
 
-    /* Multiply P by e in group G2 */
+    /**
+      * Multiply P by e in group G2
+      *
+      * @this {PAIR256}
+      * @param P Member of G2
+      * @param e BIG multiplier
+      * @return R Member of G2 R=e.P
+      */
     PAIR256.G2mul = function(P, e) {
         var R, Q, F, q, u, t, i, np, nn;
 
@@ -635,7 +711,14 @@
         return R;
     };
 
-    /* Note that this method requires a lot of RAM! Better to use compressed XTR method, see ctx.FP4.js */
+    /**
+      * Fast raising of a member of GT to a BIG power
+      *
+      * @this {PAIR256}
+      * @param d Member of GT
+      * @param e BIG exponent
+      * @return r d^e
+      */    
     PAIR256.GTpow = function(d, e) {
         var r, g, fa, fb, f, q, t, u, i, np, nn;
 
diff --git a/src/rand.js b/src/rand.js
index db110b0..d5200a7 100644
--- a/src/rand.js
+++ b/src/rand.js
@@ -31,6 +31,12 @@
 var RAND = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of RAND
+      *
+      * @constructor
+      * @this {RAND}
+      */            
     var RAND = function() {
         /* Cryptographically strong pseudo-random number generator */
         this.ira = []; /* random number...   */
@@ -46,7 +52,11 @@
         NJ: 6,
         NV: 8,
 
-        /* Terminate and clean up */
+	/**
+         * Delete all internal state of a random number generator
+         *
+         * @this {RAND}
+         */			
         clean: function() {
             var i;
 
@@ -63,7 +73,12 @@
             this.pool_ptr = 0;
         },
 
-        sbrand: function() { /* Marsaglia & Zaman random number generator */
+	/**
+         * Marsaglia & Zaman random number generator
+         *
+         * @this {RAND}
+         */				
+        sbrand: function() {
             var i, k, pdiff, t;
 
             this.rndptr++;
@@ -131,7 +146,13 @@
             this.pool_ptr = 0;
         },
 
-        /* Initialize RNG with some real entropy from some external source */
+	/**
+         * Initialize RNG with some real entropy from some external source
+         *
+         * @this {RAND}
+	 * @param rawlen the number of seed bytes provided
+	 * @param raw an array of seed bytes
+         */
         seed: function(rawlen, raw) { /* initialise from at least 128 byte string of raw random entropy */
             var sh = new ctx.HASH256(),
                 digest = [],
@@ -164,7 +185,11 @@
             this.fill_pool();
         },
 
-        /* get random byte */
+	/**
+         * Get random byte
+         *
+         * @this {RAND}
+         */
         getByte: function() {
             var r = this.pool[this.pool_ptr++];
 
@@ -176,7 +201,12 @@
         }
     };
 
-    RAND.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
+    /**
+      * Pack 4 bytes into a 32-bit Word
+      *
+      * @this {RAND}
+      */    
+    RAND.pack = function(b) { 
         return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
     };
 
diff --git a/src/rsa.js b/src/rsa.js
index d04ba30..7428c14 100644
--- a/src/rsa.js
+++ b/src/rsa.js
@@ -25,6 +25,12 @@
 RSA = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of RSA
+      *
+      * @constructor
+      * @this {RSA}
+      */            
     var RSA = {
         RFS: ctx.BIG.MODBYTES * ctx.FF.FFLEN,
         SHA256: 32,
@@ -38,6 +44,13 @@
         SHA384ID: [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30],
         SHA512ID: [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40],
 
+	/**
+         * Convert byte array to hex string
+         *
+         * @this {RSA}
+         * @param b byte array
+         * @return s hex string
+         */			
         bytestohex: function(b) {
             var s = "",
                 len = b.length,
@@ -52,6 +65,13 @@
             return s;
         },
 
+	/**
+         * Convert byte array to string
+         *
+         * @this {RSA}
+         * @param b byte array
+         * @return s string
+         */			
         bytestostring: function(b) {
             var s = "",
                 i;
@@ -63,6 +83,13 @@
             return s;
         },
 
+	/**
+         * Convert a string to byte array
+         *
+         * @this {RSA}
+         * @param s string
+         * @return b byte array
+         */				
         stringtobytes: function(s) {
             var b = [],
                 i;
@@ -74,6 +101,15 @@
             return b;
         },
 
+	/**
+         * General purpose hash function
+         *
+         * @this {RSA}
+         * @param sha is the hash type
+         * @param A byte array
+         * @param n Integer
+         * @return R hash value
+         */					
         hashit: function(sha, A, n) {
             var R = [],
                 H;
@@ -119,6 +155,15 @@
             return R;
         },
 
+	/**
+         * RSA Key Pair Generator
+         *
+         * @this {RSA}
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param e the encryption exponent
+	 * @param PRIV the output RSA private key
+	 * @param PUB the output RSA public key
+         */						
         KEY_PAIR: function(rng, e, PRIV, PUB) { /* IEEE1363 A16.11/A16.12 more or less */
             var n = PUB.n.length >> 1,
                 t = new ctx.FF(n),
@@ -225,6 +270,16 @@
             }
         },
 
+	/**
+         * PKCS V1.5 padding of a message prior to RSA signature
+         *
+         * @this {RSA}
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param e the encryption exponent
+	 * @param PRIV the output RSA private key
+	 * @param PUB the output RSA public key
+         * @return true or false
+         */							
         PKCS15: function(sha, m, w) {
             var olen = ctx.FF.FF_BITS / 8,
                 hlen = sha,
@@ -270,7 +325,16 @@
             return true;
         },
 
-        /* OAEP Message Encoding for Encryption */
+	/**
+         * OAEP padding of a message prior to RSA encryption
+         *
+         * @this {RSA}
+	 * @param sha is the hash type
+	 * @param m is the input message
+	 * @param rng is a pointer to a cryptographically secure random number generator
+	 * @param P are input encoding parameter string (could be NULL)
+         * @return f is the output encoding, ready for RSA encryption
+         */							
         OAEP_ENCODE: function(sha, m, rng, p) {
             var olen = RSA.RFS - 1,
                 mlen = m.length,
@@ -333,7 +397,15 @@
             return f;
         },
 
-        /* OAEP Message Decoding for Decryption */
+	/**
+         * OAEP unpadding of a message after RSA decryption
+         *
+         * @this {RSA}
+	 * @param sha is the hash type
+	 * @param P are input encoding parameter string (could be NULL)
+         * @param f is the padded message
+         * @return r is the unpadded message
+         */
         OAEP_DECODE: function(sha, p, f) {
             var olen = RSA.RFS - 1,
                 SEED = [],
@@ -431,7 +503,12 @@
             return r;
         },
 
-        /* destroy the Private Key structure */
+	/**
+         * Destroy an RSA private Key
+         *
+         * @this {RSA}
+	 * @param PRIV the input RSA private key. Destroyed on output.
+         */
         PRIVATE_KEY_KILL: function(PRIV) {
             PRIV.p.zero();
             PRIV.q.zero();
@@ -440,7 +517,14 @@
             PRIV.c.zero();
         },
 
-        /* RSA encryption with the public key */
+	/**
+         * RSA encryption of suitably padded plaintext
+         *
+         * @this {RSA}
+         * @param PUB the input RSA public key
+	 * @param F is input padded message
+	 * @param G is the output ciphertext
+         */
         ENCRYPT: function(PUB, F, G) {
             var n = PUB.n.getlen(),
                 f = new ctx.FF(n);
@@ -452,7 +536,14 @@
             f.toBytes(G);
         },
 
-        /* RSA decryption with the private key */
+	/**
+         * RSA decryption of ciphertext
+         *
+         * @this {RSA}
+	 * @param PRIV the input RSA private key
+	 * @param G is the input ciphertext
+	 * @param F is output plaintext (requires unpadding)
+         */
         DECRYPT: function(PRIV, G, F) {
             var n = PRIV.p.getlen(),
                 g = new ctx.FF(2 * n),
@@ -492,6 +583,13 @@
 rsa_private_key = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of rsa_private_key
+      *
+      * @constructor
+      * @this {rsa_private_key}
+      * @param n FF length
+      */                
     var rsa_private_key = function(n) {
         this.p = new ctx.FF(n);
         this.q = new ctx.FF(n);
@@ -506,6 +604,13 @@
 rsa_public_key = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of rsa_public_key
+      *
+      * @constructor
+      * @this {rsa_private_key}
+      * @param m FF length
+      */                    
     var rsa_public_key = function(m) {
         this.e = 0;
         this.n = new ctx.FF(m);
diff --git a/src/sha3.js b/src/sha3.js
index 345de82..2c0442e 100644
--- a/src/sha3.js
+++ b/src/sha3.js
@@ -29,6 +29,13 @@
 var SHA3 = function(ctx) {
     "use strict";
 
+    /**
+      * Creates an instance of SHA3
+      *
+      * @constructor
+      * @this {SHA3}
+      * @param olen output length
+      */                
     var SHA3 = function(olen) {
         this.length = 0;
         this.rate = 0;
@@ -106,7 +113,12 @@
             }
         },
 
-        /* Initialise Hash function */
+        /**
+          * Initialise an instance of SHA3
+          *
+          * @this {SHA3}
+          * @param olen output length
+          */
         init: function(olen) { /* initialise */
             var i, j;
             for (i = 0; i < 5; i++) {
@@ -120,7 +132,12 @@
             this.rate = 200 - 2 * olen;
         },
 
-        /* process a single byte */
+        /**
+          * Process a byte for SHA3
+          *
+          * @this {SHA3}
+          * @byt byte of date to be processed
+          */
         process: function(byt) { /* process the next message byte */
             var i, j, k, b, cnt, el;
 
@@ -183,6 +200,12 @@
             }
         },
 
+        /**
+          * Create fixed length hash output of SHA3
+          *
+          * @this {SHA3}
+          * @param buff byte array to store hash
+          */	
         hash: function(buff) { /* pad message and finish - supply digest */
             var q = this.rate - (this.length % this.rate);
             if (q == 1) {
@@ -197,6 +220,13 @@
             this.squeeze(buff, this.len);
         },
 
+        /**
+          * Create variable length hash output of SHA3
+          *
+          * @this {SHA3}
+          * @param buff byte array to store hash
+          * @param olen length of the hash
+          */		
         shake: function(buff, olen) { /* pad message and finish - supply digest */
             var q = this.rate - (this.length % this.rate);
             if (q == 1) {
diff --git a/src/uint64.js b/src/uint64.js
index 124497a..4b769c1 100644
--- a/src/uint64.js
+++ b/src/uint64.js
@@ -22,12 +22,27 @@
 var UInt64 = function() {
     "use strict";
 
+    /**
+      * Creates an instance of UInt64. Rudimentary unsigned 64-bit type for SHA384 and SHA512 
+      *
+      * @constructor
+      * @this {UInt64}
+      * @param top Top 32 bits
+      * @param bot Bottom 32 bits
+      */                
     var UInt64 = function(top, bot) {
         this.top = top;
         this.bot = bot;
     };
 
     UInt64.prototype = {
+
+	/**
+         * Add value
+         *
+         * @this {UInt64}
+         * @param y UInt64 value
+         */				
         add: function(y) {
             var t = (this.bot >>> 0) + (y.bot >>> 0),
                 low = t >>> 0,
@@ -44,11 +59,21 @@
             return this;
         },
 
+	/**
+         * Copy value
+         *
+         * @this {UInt64}
+         */					
         copy: function() {
             var r = new UInt64(this.top, this.bot);
             return r;
         },
 
+	/**
+         * Shift left
+         *
+         * @this {UInt64}
+         */						
         shlb: function() {
             var t = this.bot >>> 24;
             this.top = t + (this.top << 8);
diff --git a/test/test_AES.js b/test/test_AES.js
index b0b7074..3c65c5e 100644
--- a/test/test_AES.js
+++ b/test/test_AES.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test AES function - test driver and function exerciser for AES API Functions */
 
 var CTX = require("../index");
@@ -240,4 +239,4 @@
         done();
     });
 
-});
\ No newline at end of file
+});
diff --git a/test/test_BIG.js b/test/test_BIG.js
index 0ba368e..c047407 100644
--- a/test/test_BIG.js
+++ b/test/test_BIG.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test BIG consistency - test driver and function exerciser for BIG API Functions */
 var chai = require('chai');
 
diff --git a/test/test_BLS.js b/test/test_BLS.js
index 9b8d2bb..90df161 100644
--- a/test/test_BLS.js
+++ b/test/test_BLS.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 // Test BLS
diff --git a/test/test_DVS.js b/test/test_DVS.js
index 3f9eeea..8418f3b 100644
--- a/test/test_DVS.js
+++ b/test/test_DVS.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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 exprtns or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
+    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.
 */
 
 /* Test DVS - test driver and function exerciser for Designated Veifier Signature API Functions */
diff --git a/test/test_ECC.js b/test/test_ECC.js
index b267ced..e292ac7 100644
--- a/test/test_ECC.js
+++ b/test/test_ECC.js
@@ -1,132 +1,131 @@
-/*

-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 exprtns or implied.  See the License for the

-specific language governing permissions and limitations

-under the License.

-*/

-

-

-/* Test ECC - test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var all_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'C25519', 'SECP256K1', 'NIST384', 'C41417', 'NIST521', 'NUMS256W',

-    'NUMS256E', 'NUMS384W', 'NUMS384E', 'NUMS512W', 'NUMS512E', 'BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'

-];

-

-all_curves.forEach(function(curve) {

-

-    var ctx = new CTX(curve);

-

-    describe('TEST ECC ' + curve, function() {

-

-        var pp = "M0ng00se",

-            sha = ctx.ECP.HASH_TYPE,

-            S1 = [],

-            W0 = [],

-            W1 = [],

-            Z0 = [],

-            Z1 = [],

-            RAW = [],

-            SALT = [],

-            P1 = [],

-            P2 = [],

-            V = [],

-            M1 = [],

-            CS = [],

-            DS = [],

-            rng = new ctx.RAND(),

-            T = new Array(12), // must specify required length

-            PW, KEY1, KEY2, C, M2, S0, rtn;

-

-        before(function(done) {

-            this.timeout(0);

-            rng.clean();

-            for (i = 0; i < 100; i++) RAW[i] = i;

-            rng.seed(100, RAW);

-            for (i = 0; i < 8; i++) SALT[i] = (i + 1); // set Salt

-            PW = ctx.ECDH.stringtobytes(pp);

-            // private key S0 of size EGS bytes derived from Password and Salt 

-            S0 = ctx.ECDH.PBKDF2(sha, PW, SALT, 1000, ctx.ECDH.EGS);

-            done();

-        });

-

-

-        it('test ECDH', function(done) {

-            this.timeout(0);

-

-            // Generate Key pair S/W 

-            ctx.ECDH.KEY_PAIR_GENERATE(null, S0, W0);

-

-            rtn = ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);

-            expect(rtn).to.be.equal(0);

-            // Random private key for other party 

-            ctx.ECDH.KEY_PAIR_GENERATE(rng, S1, W1);

-

-            rtn = ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);

-            expect(rtn).to.be.equal(0);

-

-            // Calculate common key using DH - IEEE 1363 method 

-

-            ctx.ECDH.ECPSVDP_DH(S0, W1, Z0);

-            ctx.ECDH.ECPSVDP_DH(S1, W0, Z1);

-

-            var same = true;

-            for (i = 0; i < ctx.ECDH.EFS; i++)

-                if (Z0[i] != Z1[i]) same = false;

-

-

-            KEY1 = ctx.ECDH.KDF2(sha, Z0, null, ctx.ECP.AESKEY);

-            KEY2 = ctx.ECDH.KDF2(sha, Z1, null, ctx.ECP.AESKEY);

-

-            expect(KEY1.toString()).to.be.equal(KEY2.toString());

-            done();

-        });

-

-        if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {

-            it('test ECIES', function(done) {

-                this.timeout(0);

-                P1[0] = 0x0;

-                P1[1] = 0x1;

-                P1[2] = 0x2;

-                P2[0] = 0x0;

-                P2[1] = 0x1;

-                P2[2] = 0x2;

-                P2[3] = 0x3;

-

-                for (i = 0; i <= 16; i++) M1[i] = i;

-

-                C = ctx.ECDH.ECIES_ENCRYPT(sha, P1, P2, rng, W1, M1, V, T);

-

-                M2 = ctx.ECDH.ECIES_DECRYPT(sha, P1, P2, V, C, T, S1);

-

-                expect(M1.toString()).to.equal(M2.toString());

-

-                done();

-            });

-

-            it('test ECDSA', function(done) {

-                this.timeout(0);

-                expect(ctx.ECDH.ECPSP_DSA(sha, rng, S0, M1, CS, DS)).to.be.equal(0);

-                expect(ctx.ECDH.ECPVP_DSA(sha, W0, M1, CS, DS)).to.be.equal(0);

-                done();

-            });

-        }

-    });

-});

+/*
+    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.
+*/
+
+/* Test ECC - test driver and function exerciser for ECDH/ECIES/ECDSA API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var all_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'C25519', 'SECP256K1', 'NIST384', 'C41417', 'NIST521', 'NUMS256W',
+    'NUMS256E', 'NUMS384W', 'NUMS384E', 'NUMS512W', 'NUMS512E', 'BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'
+];
+
+all_curves.forEach(function(curve) {
+
+    var ctx = new CTX(curve);
+
+    describe('TEST ECC ' + curve, function() {
+
+        var pp = "M0ng00se",
+            sha = ctx.ECP.HASH_TYPE,
+            S1 = [],
+            W0 = [],
+            W1 = [],
+            Z0 = [],
+            Z1 = [],
+            RAW = [],
+            SALT = [],
+            P1 = [],
+            P2 = [],
+            V = [],
+            M1 = [],
+            CS = [],
+            DS = [],
+            rng = new ctx.RAND(),
+            T = new Array(12), // must specify required length
+            PW, KEY1, KEY2, C, M2, S0, rtn;
+
+        before(function(done) {
+            this.timeout(0);
+            rng.clean();
+            for (i = 0; i < 100; i++) RAW[i] = i;
+            rng.seed(100, RAW);
+            for (i = 0; i < 8; i++) SALT[i] = (i + 1); // set Salt
+            PW = ctx.ECDH.stringtobytes(pp);
+            // private key S0 of size EGS bytes derived from Password and Salt 
+            S0 = ctx.ECDH.PBKDF2(sha, PW, SALT, 1000, ctx.ECDH.EGS);
+            done();
+        });
+
+
+        it('test ECDH', function(done) {
+            this.timeout(0);
+
+            // Generate Key pair S/W 
+            ctx.ECDH.KEY_PAIR_GENERATE(null, S0, W0);
+
+            rtn = ctx.ECDH.PUBLIC_KEY_VALIDATE(W0);
+            expect(rtn).to.be.equal(0);
+            // Random private key for other party 
+            ctx.ECDH.KEY_PAIR_GENERATE(rng, S1, W1);
+
+            rtn = ctx.ECDH.PUBLIC_KEY_VALIDATE(W1);
+            expect(rtn).to.be.equal(0);
+
+            // Calculate common key using DH - IEEE 1363 method 
+
+            ctx.ECDH.ECPSVDP_DH(S0, W1, Z0);
+            ctx.ECDH.ECPSVDP_DH(S1, W0, Z1);
+
+            var same = true;
+            for (i = 0; i < ctx.ECDH.EFS; i++)
+                if (Z0[i] != Z1[i]) same = false;
+
+
+            KEY1 = ctx.ECDH.KDF2(sha, Z0, null, ctx.ECP.AESKEY);
+            KEY2 = ctx.ECDH.KDF2(sha, Z1, null, ctx.ECP.AESKEY);
+
+            expect(KEY1.toString()).to.be.equal(KEY2.toString());
+            done();
+        });
+
+        if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
+            it('test ECIES', function(done) {
+                this.timeout(0);
+                P1[0] = 0x0;
+                P1[1] = 0x1;
+                P1[2] = 0x2;
+                P2[0] = 0x0;
+                P2[1] = 0x1;
+                P2[2] = 0x2;
+                P2[3] = 0x3;
+
+                for (i = 0; i <= 16; i++) M1[i] = i;
+
+                C = ctx.ECDH.ECIES_ENCRYPT(sha, P1, P2, rng, W1, M1, V, T);
+
+                M2 = ctx.ECDH.ECIES_DECRYPT(sha, P1, P2, V, C, T, S1);
+
+                expect(M1.toString()).to.equal(M2.toString());
+
+                done();
+            });
+
+            it('test ECDSA', function(done) {
+                this.timeout(0);
+                expect(ctx.ECDH.ECPSP_DSA(sha, rng, S0, M1, CS, DS)).to.be.equal(0);
+                expect(ctx.ECDH.ECPVP_DSA(sha, W0, M1, CS, DS)).to.be.equal(0);
+                done();
+            });
+        }
+    });
+});
diff --git a/test/test_ECP.js b/test/test_ECP.js
index 83b626e..7c4c97a 100644
--- a/test/test_ECP.js
+++ b/test/test_ECP.js
@@ -1,158 +1,157 @@
-/*

-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.

-*/

-

-

-/* Test ECP ARITHMETICS - test driver and function exerciser for ECP API Functions */

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var ecp_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'C25519', 'SECP256K1', 'NIST384', 'C41417',

-     'NIST521', 'NUMS256W', 'NUMS384W', 'NUMS512W', 'BN254', 'BN254CX', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'

-];

-

-var readBIG = function(string, ctx) {

-    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}

-    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));

-}

-

-var readPoint = function(string, ctx) {

-    var P = new ctx.ECP(),

-        X,Y;

-

-    string = string.split(":");

-

-    X = readBIG(string[0],ctx);

-    Y = readBIG(string[1],ctx);

-    P.setxy(X,Y);

-

-    return P;

-}

-

-describe('TEST ECP ARITHMETIC', function() {

-

-    ecp_curves.forEach(function(curve) {

-

-        it('test '+ curve, function(done) {

-            this.timeout(0);

-

-            var ctx = new CTX(curve);

-            var vectors = require('../testVectors/ecp/'+curve+'.json');

-

-            vectors.forEach(function(vector) {

-                var P1 = readPoint(vector.ECP1,ctx);

-                var Paux1 = new ctx.ECP(0);

-

-                // test copy and equals

-                Paux1.copy(P1);

-                expect(Paux1.equals(P1)).to.equal(true);

-

-                if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {

-                    // test that y^2 = RHS

-                    var x = Paux1.getx();

-                    var y = Paux1.gety();

-                    y.sqr();

-                    x = ctx.ECP.RHS(x);

-

-                    expect(x.toString()).to.equal(y.toString());

-

-		            // test commutativity of the sum

-		            var P2 = readPoint(vector.ECP2,ctx);

-		            var Psum = readPoint(vector.ECPsum,ctx);

-		            var Paux2 = new ctx.ECP(0);

-		            Paux1.copy(P1);

-		            Paux2.copy(P2);

-		            Paux1.add(P2);

-		            Paux2.add(P1);

-		            expect(Paux1.toString()).to.equal(Psum.toString());

-		            expect(Paux2.toString()).to.equal(Psum.toString());

-

-		            // test associativity of the sum

-		            Paux2.copy(P2);

-		            Paux2.add(Psum);

-		            Paux2.add(P1);

-		            Paux1.add(Psum)

-		            expect(Paux1.toString()).to.equal(Paux2.toString());

-

-                    // Test sum with infinity

-                    Paux1.copy(P1);

-                    Paux2.inf();

-                    Paux1.add(Paux2);

-                    expect(Paux1.toString()).to.equal(P1.toString());

-                    Paux2.add(Paux1);

-                    expect(Paux2.toString()).to.equal(P1.toString());

-

-	                // test negative of a point

-	                var Pneg = readPoint(vector.ECPneg,ctx);

-	                Paux1.copy(P1);

-	                Paux1.neg();

-	                expect(Paux1.toString()).to.equal(Pneg.toString());

-

-	                // test subtraction between points

-	                var Psub = readPoint(vector.ECPsub,ctx);

-	                Paux1.copy(P1);

-	                Paux1.sub(P2);

-	                expect(Paux1.toString()).to.equal(Psub.toString());

-            	}

-

-                // test doubling

-                var Pdbl = readPoint(vector.ECPdbl,ctx);

-                Paux1.copy(P1);

-                Paux1.dbl();

-                expect(Paux1.toString()).to.equal(Pdbl.toString());

-

-                // test scalar multiplication

-                var Pmul = readPoint(vector.ECPmul,ctx);

-                var Scalar1 = readBIG(vector.BIGscalar1, ctx);

-                Paux1.copy(P1);

-                Paux1 = Paux1.mul(Scalar1);

-                expect(Paux1.toString()).to.equal(Pmul.toString());

-

-                if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {

-	                // test multiplication by small integer

-	                var Ppinmul = readPoint(vector.ECPpinmul,ctx);

-	                Paux1.copy(P1);

-	                Paux1 = Paux1.pinmul(1234,14);

-	                expect(Paux1.toString()).to.equal(Ppinmul.toString());

-

-	                // test mul2

-	                var Pmul2 = readPoint(vector.ECPmul2,ctx);

-                    var Scalar1 = readBIG(vector.BIGscalar1, ctx);

-	                var Scalar2 = readBIG(vector.BIGscalar2, ctx);

-	                Paux1.copy(P1);

-	                Paux2.copy(P2);

-	                Paux1 = Paux1.mul2(Scalar1,Paux2,Scalar2);

-	                expect(Paux1.toString()).to.equal(Pmul2.toString());

-	            }

-

-                // test wrong coordinates and infinity point

-                var Pwrong = readPoint(vector.ECPwrong,ctx);

-                var Pinf = readPoint(vector.ECPinf,ctx);

-                // test copy and equals

-                expect(Pwrong.is_infinity()).to.equal(true);

-                expect(Pinf.is_infinity()).to.equal(true);

-                expect(Pwrong.equals(Pinf)).to.equal(true);

-            });

-            done();

-        });

-    });

-});
\ No newline at end of file
+/*
+    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.
+*/
+
+/* Test ECP ARITHMETICS - test driver and function exerciser for ECP API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var ecp_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'C25519', 'SECP256K1', 'NIST384', 'C41417',
+     'NIST521', 'NUMS256W', 'NUMS384W', 'NUMS512W', 'BN254', 'BN254CX', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'
+];
+
+var readBIG = function(string, ctx) {
+    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readPoint = function(string, ctx) {
+    var P = new ctx.ECP(),
+        X,Y;
+
+    string = string.split(":");
+
+    X = readBIG(string[0],ctx);
+    Y = readBIG(string[1],ctx);
+    P.setxy(X,Y);
+
+    return P;
+}
+
+describe('TEST ECP ARITHMETIC', function() {
+
+    ecp_curves.forEach(function(curve) {
+
+        it('test '+ curve, function(done) {
+            this.timeout(0);
+
+            var ctx = new CTX(curve);
+            var vectors = require('../testVectors/ecp/'+curve+'.json');
+
+            vectors.forEach(function(vector) {
+                var P1 = readPoint(vector.ECP1,ctx);
+                var Paux1 = new ctx.ECP(0);
+
+                // test copy and equals
+                Paux1.copy(P1);
+                expect(Paux1.equals(P1)).to.equal(true);
+
+                if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
+                    // test that y^2 = RHS
+                    var x = Paux1.getx();
+                    var y = Paux1.gety();
+                    y.sqr();
+                    x = ctx.ECP.RHS(x);
+
+                    expect(x.toString()).to.equal(y.toString());
+
+		            // test commutativity of the sum
+		            var P2 = readPoint(vector.ECP2,ctx);
+		            var Psum = readPoint(vector.ECPsum,ctx);
+		            var Paux2 = new ctx.ECP(0);
+		            Paux1.copy(P1);
+		            Paux2.copy(P2);
+		            Paux1.add(P2);
+		            Paux2.add(P1);
+		            expect(Paux1.toString()).to.equal(Psum.toString());
+		            expect(Paux2.toString()).to.equal(Psum.toString());
+
+		            // test associativity of the sum
+		            Paux2.copy(P2);
+		            Paux2.add(Psum);
+		            Paux2.add(P1);
+		            Paux1.add(Psum)
+		            expect(Paux1.toString()).to.equal(Paux2.toString());
+
+                    // Test sum with infinity
+                    Paux1.copy(P1);
+                    Paux2.inf();
+                    Paux1.add(Paux2);
+                    expect(Paux1.toString()).to.equal(P1.toString());
+                    Paux2.add(Paux1);
+                    expect(Paux2.toString()).to.equal(P1.toString());
+
+	                // test negative of a point
+	                var Pneg = readPoint(vector.ECPneg,ctx);
+	                Paux1.copy(P1);
+	                Paux1.neg();
+	                expect(Paux1.toString()).to.equal(Pneg.toString());
+
+	                // test subtraction between points
+	                var Psub = readPoint(vector.ECPsub,ctx);
+	                Paux1.copy(P1);
+	                Paux1.sub(P2);
+	                expect(Paux1.toString()).to.equal(Psub.toString());
+            	}
+
+                // test doubling
+                var Pdbl = readPoint(vector.ECPdbl,ctx);
+                Paux1.copy(P1);
+                Paux1.dbl();
+                expect(Paux1.toString()).to.equal(Pdbl.toString());
+
+                // test scalar multiplication
+                var Pmul = readPoint(vector.ECPmul,ctx);
+                var Scalar1 = readBIG(vector.BIGscalar1, ctx);
+                Paux1.copy(P1);
+                Paux1 = Paux1.mul(Scalar1);
+                expect(Paux1.toString()).to.equal(Pmul.toString());
+
+                if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
+	                // test multiplication by small integer
+	                var Ppinmul = readPoint(vector.ECPpinmul,ctx);
+	                Paux1.copy(P1);
+	                Paux1 = Paux1.pinmul(1234,14);
+	                expect(Paux1.toString()).to.equal(Ppinmul.toString());
+
+	                // test mul2
+	                var Pmul2 = readPoint(vector.ECPmul2,ctx);
+                    var Scalar1 = readBIG(vector.BIGscalar1, ctx);
+	                var Scalar2 = readBIG(vector.BIGscalar2, ctx);
+	                Paux1.copy(P1);
+	                Paux2.copy(P2);
+	                Paux1 = Paux1.mul2(Scalar1,Paux2,Scalar2);
+	                expect(Paux1.toString()).to.equal(Pmul2.toString());
+	            }
+
+                // test wrong coordinates and infinity point
+                var Pwrong = readPoint(vector.ECPwrong,ctx);
+                var Pinf = readPoint(vector.ECPinf,ctx);
+                // test copy and equals
+                expect(Pwrong.is_infinity()).to.equal(true);
+                expect(Pinf.is_infinity()).to.equal(true);
+                expect(Pwrong.equals(Pinf)).to.equal(true);
+            });
+            done();
+        });
+    });
+});
diff --git a/test/test_ECP2.js b/test/test_ECP2.js
index ab405cc..c19d9b7 100644
--- a/test/test_ECP2.js
+++ b/test/test_ECP2.js
@@ -1,150 +1,149 @@
-/*

-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.

-*/

-

-

-/* Test ECP2 ARITHMETICS - test driver and function exerciser for ECP2 API Functions */

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN'];

-

-var readBIG = function(string, ctx) {

-    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}

-    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));

-}

-

-var readPoint2 = function(string, ctx) {

-    var P = new ctx.ECP2(),

-        X, Y;

-

-    var coxy = string.split("&");

-    var cox = coxy[0].split(":");

-    var coy = coxy[1].split(":");

-

-    var x1 = readBIG(cox[0],ctx);

-    var x2 = readBIG(cox[1],ctx);

-    var y1 = readBIG(coy[0],ctx);

-    var y2 = readBIG(coy[1],ctx);

-

-    X = new ctx.FP2(x1,x2);

-    Y = new ctx.FP2(y1,y2);

-    P.setxy(X,Y);

-

-    return P;

-}

-

-describe('TEST ECP2 ARITHMETIC', function() {

-

-    pf_curves.forEach(function(curve) {

-

-        it('test '+curve, function(done) {

-            this.timeout(0);

-

-            var ctx = new CTX(curve);

-            var vectors = require('../testVectors/ecp2/'+curve+'.json');

-

-            var i = 0;

-            vectors.forEach(function(vector) {

-                var P1 = readPoint2(vector.ECP21,ctx);

-                var Paux1 = new ctx.ECP2(0);

-

-                // test copy and equals

-                Paux1.copy(P1);

-                expect(Paux1.equals(P1)).to.equal(true);

-

-                // test that y^2 = RHS

-                var x = Paux1.getx();

-                var y = Paux1.gety();

-                y.sqr();

-                var res = ctx.ECP2.RHS(x);

-

-                expect(res.toString()).to.equal(y.toString());

-

-                // test commutativity of the sum

-                var P2 = readPoint2(vector.ECP22,ctx);

-                var Psum = readPoint2(vector.ECP2sum,ctx);

-                var Paux2 = new ctx.ECP2(0);

-                Paux1.copy(P1);

-                Paux2.copy(P2);

-                Paux1.add(P2);

-                Paux2.add(P1);

-                expect(Paux1.toString()).to.equal(Psum.toString());

-                expect(Paux2.toString()).to.equal(Psum.toString());

-

-                // test associativity of the sum

-                Paux2.copy(P1);

-                Paux2.add(P2);

-                Paux2.add(Psum);

-                Paux1.add(Psum)

-                expect(Paux1.toString()).to.equal(Paux2.toString());

-

-                // test negative of a point

-                var Pneg = readPoint2(vector.ECP2neg,ctx);

-                Paux1.copy(P1);

-                Paux1.neg();

-                expect(Paux1.toString()).to.equal(Pneg.toString());

-

-                // test subtraction between points

-                var Psub = readPoint2(vector.ECP2sub,ctx);

-                Paux1.copy(P1);

-                Paux1.sub(P2);

-                expect(Paux1.toString()).to.equal(Psub.toString());

-

-                // test doubling

-                var Pdbl = readPoint2(vector.ECP2dbl,ctx);

-                Paux1.copy(P1);

-                Paux1.dbl();

-                expect(Paux1.toString()).to.equal(Pdbl.toString());

-

-                // test scalar multiplication

-                var Pmul = readPoint2(vector.ECP2mul,ctx);

-                var Scalar1 = readBIG(vector.BIGscalar1, ctx);

-                Paux1.copy(P1);

-                Paux1 = Paux1.mul(Scalar1);

-                expect(Paux1.toString()).to.equal(Pmul.toString());

-

-                // test linear mul4, linear combination of 4 points

-                // Only executed once for timing reasons

-                if (i===0){

-                    i++;

-                    var P3 = readPoint2(vector.ECP23,ctx);

-                    var P4 = readPoint2(vector.ECP24,ctx);

-                    var Scalar2 = readBIG(vector.BIGscalar2, ctx);

-                    var Scalar3 = readBIG(vector.BIGscalar3, ctx);

-                    var Scalar4 = readBIG(vector.BIGscalar4, ctx);

-                    var Pmul4 = readPoint2(vector.ECP2mul4,ctx);

-                    Paux1 = ctx.ECP2.mul4([P1,P2,P3,P4],[Scalar1,Scalar2,Scalar3,Scalar4]);

-                    expect(Paux1.toString()).to.equal(Pmul4.toString());

-                }

-

-                // test wrong coordinates and infinity point

-                var Pwrong = readPoint2(vector.ECP2wrong,ctx);

-                var Pinf = readPoint2(vector.ECP2inf,ctx);

-                expect(Pwrong.is_infinity()).to.equal(true);

-                expect(Pinf.is_infinity()).to.equal(true);

-                expect(Pwrong.equals(Pinf)).to.equal(true);

-            });

-            done();

-        });

-    });

-});
\ No newline at end of file
+/*
+    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.
+*/
+
+/* Test ECP2 ARITHMETICS - test driver and function exerciser for ECP2 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN'];
+
+var readBIG = function(string, ctx) {
+    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readPoint2 = function(string, ctx) {
+    var P = new ctx.ECP2(),
+        X, Y;
+
+    var coxy = string.split("&");
+    var cox = coxy[0].split(":");
+    var coy = coxy[1].split(":");
+
+    var x1 = readBIG(cox[0],ctx);
+    var x2 = readBIG(cox[1],ctx);
+    var y1 = readBIG(coy[0],ctx);
+    var y2 = readBIG(coy[1],ctx);
+
+    X = new ctx.FP2(x1,x2);
+    Y = new ctx.FP2(y1,y2);
+    P.setxy(X,Y);
+
+    return P;
+}
+
+describe('TEST ECP2 ARITHMETIC', function() {
+
+    pf_curves.forEach(function(curve) {
+
+        it('test '+curve, function(done) {
+            this.timeout(0);
+
+            var ctx = new CTX(curve);
+            var vectors = require('../testVectors/ecp2/'+curve+'.json');
+
+            var i = 0;
+            vectors.forEach(function(vector) {
+                var P1 = readPoint2(vector.ECP21,ctx);
+                var Paux1 = new ctx.ECP2(0);
+
+                // test copy and equals
+                Paux1.copy(P1);
+                expect(Paux1.equals(P1)).to.equal(true);
+
+                // test that y^2 = RHS
+                var x = Paux1.getx();
+                var y = Paux1.gety();
+                y.sqr();
+                var res = ctx.ECP2.RHS(x);
+
+                expect(res.toString()).to.equal(y.toString());
+
+                // test commutativity of the sum
+                var P2 = readPoint2(vector.ECP22,ctx);
+                var Psum = readPoint2(vector.ECP2sum,ctx);
+                var Paux2 = new ctx.ECP2(0);
+                Paux1.copy(P1);
+                Paux2.copy(P2);
+                Paux1.add(P2);
+                Paux2.add(P1);
+                expect(Paux1.toString()).to.equal(Psum.toString());
+                expect(Paux2.toString()).to.equal(Psum.toString());
+
+                // test associativity of the sum
+                Paux2.copy(P1);
+                Paux2.add(P2);
+                Paux2.add(Psum);
+                Paux1.add(Psum)
+                expect(Paux1.toString()).to.equal(Paux2.toString());
+
+                // test negative of a point
+                var Pneg = readPoint2(vector.ECP2neg,ctx);
+                Paux1.copy(P1);
+                Paux1.neg();
+                expect(Paux1.toString()).to.equal(Pneg.toString());
+
+                // test subtraction between points
+                var Psub = readPoint2(vector.ECP2sub,ctx);
+                Paux1.copy(P1);
+                Paux1.sub(P2);
+                expect(Paux1.toString()).to.equal(Psub.toString());
+
+                // test doubling
+                var Pdbl = readPoint2(vector.ECP2dbl,ctx);
+                Paux1.copy(P1);
+                Paux1.dbl();
+                expect(Paux1.toString()).to.equal(Pdbl.toString());
+
+                // test scalar multiplication
+                var Pmul = readPoint2(vector.ECP2mul,ctx);
+                var Scalar1 = readBIG(vector.BIGscalar1, ctx);
+                Paux1.copy(P1);
+                Paux1 = Paux1.mul(Scalar1);
+                expect(Paux1.toString()).to.equal(Pmul.toString());
+
+                // test linear mul4, linear combination of 4 points
+                // Only executed once for timing reasons
+                if (i===0){
+                    i++;
+                    var P3 = readPoint2(vector.ECP23,ctx);
+                    var P4 = readPoint2(vector.ECP24,ctx);
+                    var Scalar2 = readBIG(vector.BIGscalar2, ctx);
+                    var Scalar3 = readBIG(vector.BIGscalar3, ctx);
+                    var Scalar4 = readBIG(vector.BIGscalar4, ctx);
+                    var Pmul4 = readPoint2(vector.ECP2mul4,ctx);
+                    Paux1 = ctx.ECP2.mul4([P1,P2,P3,P4],[Scalar1,Scalar2,Scalar3,Scalar4]);
+                    expect(Paux1.toString()).to.equal(Pmul4.toString());
+                }
+
+                // test wrong coordinates and infinity point
+                var Pwrong = readPoint2(vector.ECP2wrong,ctx);
+                var Pinf = readPoint2(vector.ECP2inf,ctx);
+                expect(Pwrong.is_infinity()).to.equal(true);
+                expect(Pinf.is_infinity()).to.equal(true);
+                expect(Pwrong.equals(Pinf)).to.equal(true);
+            });
+            done();
+        });
+    });
+});
diff --git a/test/test_ECP4.js b/test/test_ECP4.js
index bdcde8f..e148566 100644
--- a/test/test_ECP4.js
+++ b/test/test_ECP4.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test ECP4 ARITHMETICS - test driver and function exerciser for ECP4 API Functions */
 
 var chai = require('chai');
@@ -157,4 +156,4 @@
             done();
         });
     });
-});
\ No newline at end of file
+});
diff --git a/test/test_ECP8.js b/test/test_ECP8.js
index aec4fe4..b696060 100644
--- a/test/test_ECP8.js
+++ b/test/test_ECP8.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test ECP8 ARITHMETICS - test driver and function exerciser for ECP8 API Functions */
 
 var chai = require('chai');
@@ -157,4 +156,4 @@
             done();
         });
     });
-});
\ No newline at end of file
+});
diff --git a/test/test_FP12_js b/test/test_FP12_js
index 49ea61c..0a07ac3 100644
--- a/test/test_FP12_js
+++ b/test/test_FP12_js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test FP12 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
 
 var chai = require('chai');
diff --git a/test/test_FP16_js b/test/test_FP16_js
index 7ff7511..efba770 100644
--- a/test/test_FP16_js
+++ b/test/test_FP16_js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test FP16 ARITHMETICS - test driver and function exerciser for FP16 API Functions */
 
 var chai = require('chai');
diff --git a/test/test_FP24_js b/test/test_FP24_js
index da76b0f..5c85e2d 100644
--- a/test/test_FP24_js
+++ b/test/test_FP24_js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test FP24 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
 
 var chai = require('chai');
diff --git a/test/test_FP2_js b/test/test_FP2_js
index 06a31e0..abedc07 100644
--- a/test/test_FP2_js
+++ b/test/test_FP2_js
@@ -1,164 +1,163 @@
-/*

-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.

-*/

-

-

-/* Test FP2 ARITHMETICS - test driver and function exerciser for FP2 API Functions */

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];

-

-var readBIG = function(string, ctx) {

-    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}

-    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));

-}

-

-var readFP2 = function(string, ctx) {

-

-    string = string.split(",");

-    var cox = string[0].slice(1);

-    var coy = string[1].slice(0,-1);

-

-    var x = readBIG(cox,ctx);

-    var y = readBIG(coy,ctx);

-

-    return new ctx.FP2(x,y);

-}

-

-describe('TEST FP2 ARITHMETIC', function() {

-

-    pf_curves.forEach(function(curve){

-

-        it('test '+ curve, function(done) {

-            this.timeout(0);

-

-            var ctx = new CTX(curve);

-            var vectors = require('../testVectors/fp2/'+curve+'.json');

-            var i=0;

-

-            vectors.forEach(function(vector){

-

-                // test commutativity of addition

-                var fp21 = readFP2(vector.FP21,ctx);

-                var fp22 = readFP2(vector.FP22,ctx);

-                var fp2add = readFP2(vector.FP2add,ctx);

-                var a1 = new ctx.FP2(0);

-                var a2 = new ctx.FP2(0);

-                a1.copy(fp21);

-                a1.add(fp22);

-                expect(a1.toString()).to.equal(fp2add.toString());

-                a2.copy(fp22);

-                a2.add(fp21);

-                expect(a2.toString()).to.equal(fp2add.toString());

-

-                // test associativity of addition

-                a2.add(fp2add);

-                a1.copy(fp21);

-                a1.add(fp2add);

-                a1.add(fp22);

-                expect(a1.toString()).to.equal(a2.toString());

-

-                // test subtraction

-                var fp2sub = readFP2(vector.FP2sub, ctx);

-                a1.copy(fp21);

-                a1.sub(fp22);

-                expect(a1.toString()).to.equal(fp2sub.toString());

-

-                // test negative of a FP2

-                var fp2neg = readFP2(vector.FP2neg, ctx);

-                a1.copy(fp21);

-                a1.neg();

-                expect(a1.toString()).to.equal(fp2neg.toString());

-

-                // test conjugate of a FP2

-                var fp2conj = readFP2(vector.FP2conj, ctx);

-                a1.copy(fp21);

-                a1.conj();

-                expect(a1.toString()).to.equal(fp2conj.toString());

-

-                // test scalar multiplication

-                var fp2pmul = readFP2(vector.FP2pmul, ctx);

-                var scalar = readBIG(vector.BIGsc, ctx);

-                var fpsc = new ctx.FP(0);

-                fpsc.bcopy(scalar);

-                a1.copy(fp21);

-                a1.pmul(fpsc);

-                expect(a1.toString()).to.equal(fp2pmul.toString());

-

-                // test small scalar multiplication

-                var fp2imul = readFP2(vector.FP2imul, ctx);

-                a1.copy(fp21);

-                a1.imul(i);

-                expect(a1.toString()).to.equal(fp2imul.toString());

-                i++;

-

-                // test square and square root

-                var fp2sqr = readFP2(vector.FP2sqr, ctx);

-                a1.copy(fp21);

-                a1.sqr();

-                expect(a1.toString()).to.equal(fp2sqr.toString());

-                a1.sqrt();

-                a1.sqr();

-                expect(a1.toString()).to.equal(fp2sqr.toString());

-

-                // test multiplication

-                var fp2mul = readFP2(vector.FP2mul, ctx);

-                a1.copy(fp21);

-                a2.copy(fp22);

-                a1.mul(a2);

-                expect(a1.toString()).to.equal(fp2mul.toString());

-

-                // test power

-                var fp2pow = readFP2(vector.FP2pow, ctx);

-                a1 = fp21.pow(scalar);

-                expect(a1.toString()).to.equal(fp2pow.toString());

-

-                // test inverse

-                var fp2inv = readFP2(vector.FP2inv, ctx);

-                a1.copy(fp21);

-                a1.inverse();

-                expect(a1.toString()).to.equal(fp2inv.toString());

-

-                // test division by 2

-                var fp2div2 = readFP2(vector.FP2div2, ctx);

-                a1.copy(fp21);

-                a1.div2();

-                expect(a1.toString()).to.equal(fp2div2.toString());

-

-                // test multiplication by (1+sqrt(-1))

-                var fp2mulip = readFP2(vector.FP2mulip, ctx);

-                a1.copy(fp21);

-                a1.mul_ip();

-                expect(a1.toString()).to.equal(fp2mulip.toString());

-

-                // test division by (1+sqrt(-1))

-                var fp2divip = readFP2(vector.FP2divip, ctx);

-                a1.copy(fp21);

-                a1.div_ip();

-                expect(a1.toString()).to.equal(fp2divip.toString());

-

-            });

-            done();

-        });

-    });

+/*
+    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.
+*/
+
+/* Test FP2 ARITHMETICS - test driver and function exerciser for FP2 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];
+
+var readBIG = function(string, ctx) {
+    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP2 = function(string, ctx) {
+
+    string = string.split(",");
+    var cox = string[0].slice(1);
+    var coy = string[1].slice(0,-1);
+
+    var x = readBIG(cox,ctx);
+    var y = readBIG(coy,ctx);
+
+    return new ctx.FP2(x,y);
+}
+
+describe('TEST FP2 ARITHMETIC', function() {
+
+    pf_curves.forEach(function(curve){
+
+        it('test '+ curve, function(done) {
+            this.timeout(0);
+
+            var ctx = new CTX(curve);
+            var vectors = require('../testVectors/fp2/'+curve+'.json');
+            var i=0;
+
+            vectors.forEach(function(vector){
+
+                // test commutativity of addition
+                var fp21 = readFP2(vector.FP21,ctx);
+                var fp22 = readFP2(vector.FP22,ctx);
+                var fp2add = readFP2(vector.FP2add,ctx);
+                var a1 = new ctx.FP2(0);
+                var a2 = new ctx.FP2(0);
+                a1.copy(fp21);
+                a1.add(fp22);
+                expect(a1.toString()).to.equal(fp2add.toString());
+                a2.copy(fp22);
+                a2.add(fp21);
+                expect(a2.toString()).to.equal(fp2add.toString());
+
+                // test associativity of addition
+                a2.add(fp2add);
+                a1.copy(fp21);
+                a1.add(fp2add);
+                a1.add(fp22);
+                expect(a1.toString()).to.equal(a2.toString());
+
+                // test subtraction
+                var fp2sub = readFP2(vector.FP2sub, ctx);
+                a1.copy(fp21);
+                a1.sub(fp22);
+                expect(a1.toString()).to.equal(fp2sub.toString());
+
+                // test negative of a FP2
+                var fp2neg = readFP2(vector.FP2neg, ctx);
+                a1.copy(fp21);
+                a1.neg();
+                expect(a1.toString()).to.equal(fp2neg.toString());
+
+                // test conjugate of a FP2
+                var fp2conj = readFP2(vector.FP2conj, ctx);
+                a1.copy(fp21);
+                a1.conj();
+                expect(a1.toString()).to.equal(fp2conj.toString());
+
+                // test scalar multiplication
+                var fp2pmul = readFP2(vector.FP2pmul, ctx);
+                var scalar = readBIG(vector.BIGsc, ctx);
+                var fpsc = new ctx.FP(0);
+                fpsc.bcopy(scalar);
+                a1.copy(fp21);
+                a1.pmul(fpsc);
+                expect(a1.toString()).to.equal(fp2pmul.toString());
+
+                // test small scalar multiplication
+                var fp2imul = readFP2(vector.FP2imul, ctx);
+                a1.copy(fp21);
+                a1.imul(i);
+                expect(a1.toString()).to.equal(fp2imul.toString());
+                i++;
+
+                // test square and square root
+                var fp2sqr = readFP2(vector.FP2sqr, ctx);
+                a1.copy(fp21);
+                a1.sqr();
+                expect(a1.toString()).to.equal(fp2sqr.toString());
+                a1.sqrt();
+                a1.sqr();
+                expect(a1.toString()).to.equal(fp2sqr.toString());
+
+                // test multiplication
+                var fp2mul = readFP2(vector.FP2mul, ctx);
+                a1.copy(fp21);
+                a2.copy(fp22);
+                a1.mul(a2);
+                expect(a1.toString()).to.equal(fp2mul.toString());
+
+                // test power
+                var fp2pow = readFP2(vector.FP2pow, ctx);
+                a1 = fp21.pow(scalar);
+                expect(a1.toString()).to.equal(fp2pow.toString());
+
+                // test inverse
+                var fp2inv = readFP2(vector.FP2inv, ctx);
+                a1.copy(fp21);
+                a1.inverse();
+                expect(a1.toString()).to.equal(fp2inv.toString());
+
+                // test division by 2
+                var fp2div2 = readFP2(vector.FP2div2, ctx);
+                a1.copy(fp21);
+                a1.div2();
+                expect(a1.toString()).to.equal(fp2div2.toString());
+
+                // test multiplication by (1+sqrt(-1))
+                var fp2mulip = readFP2(vector.FP2mulip, ctx);
+                a1.copy(fp21);
+                a1.mul_ip();
+                expect(a1.toString()).to.equal(fp2mulip.toString());
+
+                // test division by (1+sqrt(-1))
+                var fp2divip = readFP2(vector.FP2divip, ctx);
+                a1.copy(fp21);
+                a1.div_ip();
+                expect(a1.toString()).to.equal(fp2divip.toString());
+
+            });
+            done();
+        });
+    });
 });
\ No newline at end of file
diff --git a/test/test_FP48_js b/test/test_FP48_js
index 5312e44..eecfcd6 100644
--- a/test/test_FP48_js
+++ b/test/test_FP48_js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test FP48 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
diff --git a/test/test_FP4_js b/test/test_FP4_js
index 2057a6c..cefec53 100644
--- a/test/test_FP4_js
+++ b/test/test_FP4_js
@@ -1,257 +1,256 @@
-/*

-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.

-*/

-

-

-/* Test FP4 ARITHMETICS - test driver and function exerciser for FP4 API Functions */

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];

-

-var readBIG = function(string, ctx) {

-    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}

-    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));

-}

-

-var readFP2 = function(string, ctx) {

-    string = string.split(",");

-    var cox = string[0].slice(1);

-    var coy = string[1].slice(0,-1);

-

-    var x = readBIG(cox,ctx);

-    var y = readBIG(coy,ctx);

-

-    return new ctx.FP2(x,y);;

-}

-

-var readFP4 = function(string, ctx) {

-    var X, Y;

-

-    string = string.split("],[");

-    var cox = string[0].slice(1) + "]";

-    var coy = "[" + string[1].slice(0,-1);

-

-    X = readFP2(cox,ctx);

-    Y = readFP2(coy,ctx);

-

-    return new ctx.FP4(X,Y);

-}

-

-describe('TEST FP4 ARITHMETIC', function() {

-

-    pf_curves.forEach(function(curve){

-

-        it('test '+ curve, function(done) {

-            this.timeout(0);

-

-            var ctx = new CTX(curve);

-            var vectors = require('../testVectors/fp4/'+curve+'.json');

-            var i=0;

-

-            var a1 = new ctx.FP4(1),

-                a2 = new ctx.FP4(0),

-                one = new ctx.FP4(1),

-                zero = new ctx.FP4(0),

-                fp2one = new ctx.FP2(1),

-                fp2zero = new ctx.FP2(0);

-

-            // Test iszilch and isunity

-            expect(zero.iszilch()).to.be.true;

-            expect(one.iszilch()).to.be.false;

-            expect(zero.isunity()).to.be.false;

-            expect(one.isunity()).to.be.true;

-

-            // Test real/isreal

-            expect(one.isreal()).to.be.true;

-            expect(one.real().toString()).to.be.equal(fp2one.toString());

-            one.times_i();

-            expect(one.isreal()).to.be.false;

-            expect(one.real().toString()).to.be.equal(fp2zero.toString());

-

-            // Test set using FP2

-            one.set(fp2one,fp2zero);

-            expect(one.isunity()).to.be.true;

-            one.seta(fp2one);

-            expect(one.isunity()).to.be.true;

-

-            // Test handling sqrt 0,1

-            a1.zero();

-            expect(a1.sqrt()).to.be.true;

-            expect(a1.toString()).to.equal(zero.toString());

-            a1.one();

-            expect(a1.sqrt()).to.be.true;

-            expect(a1.toString()).to.equal(one.toString());

-

-            vectors.forEach(function(vector){

-

-                // test commutativity of addition

-                var fp41 = readFP4(vector.FP41,ctx);

-                var fp42 = readFP4(vector.FP42,ctx);

-                var fp4add = readFP4(vector.FP4add,ctx);

-

-                a1.copy(fp41);

-                a1.add(fp42);

-                expect(a1.toString()).to.equal(fp4add.toString());

-                a2.copy(fp42);

-                a2.add(fp41);

-                expect(a2.toString()).to.equal(fp4add.toString());

-

-                // test associativity of addition

-                a2.add(fp4add);

-                a1.copy(fp41);

-                a1.add(fp4add);

-                a1.add(fp42);

-                expect(a1.toString()).to.equal(a2.toString());

-

-                // test subtraction

-                var fp4sub = readFP4(vector.FP4sub, ctx);

-                a1.copy(fp41);

-                a1.sub(fp42);

-                expect(a1.toString()).to.equal(fp4sub.toString());

-

-                // test negative of a FP4

-                var fp4neg = readFP4(vector.FP4neg, ctx);

-                a1.copy(fp41);

-                a1.neg();

-                expect(a1.toString()).to.equal(fp4neg.toString());

-

-                // test conjugate of a FP4

-                var fp4conj = readFP4(vector.FP4conj, ctx);

-                a1.copy(fp41);

-                a1.conj();

-                expect(a1.toString()).to.equal(fp4conj.toString());

-

-                // test negative conjugate of a FP4

-                var fp4nconj = readFP4(vector.FP4nconj, ctx);

-                a1.copy(fp41);

-                a1.nconj();

-                expect(a1.toString()).to.equal(fp4nconj.toString());

-

-                // test multiplication by FP2

-                var fp4pmul = readFP4(vector.FP4pmul, ctx);

-                var fp2sc = readFP2(vector.FP2sc, ctx);

-                a1.copy(fp41);

-                a1.pmul(fp2sc);

-                expect(a1.toString()).to.equal(fp4pmul.toString());

-

-                // test small scalar multiplication

-                var fp4imul = readFP4(vector.FP4imul, ctx);

-                a1.copy(fp41);

-                a1.imul(i);

-                expect(a1.toString()).to.equal(fp4imul.toString());

-                i++;

-

-                // test square

-                var fp4sqr = readFP4(vector.FP4sqr, ctx);

-                a1.copy(fp41);

-                a1.sqr();

-                expect(a1.toString()).to.equal(fp4sqr.toString());

-

-                // test multiplication

-                var fp4mul = readFP4(vector.FP4mul, ctx);

-                a1.copy(fp41);

-                a1.mul(fp42);

-                expect(a1.toString()).to.equal(fp4mul.toString());

-

-                // test power

-                var fp4pow = readFP4(vector.FP4pow, ctx);

-                var BIGsc1 = readBIG(vector.BIGsc1, ctx);

-                a1 = fp41.pow(BIGsc1);

-                expect(a1.toString()).to.equal(fp4pow.toString());

-

-                // test inverse

-                var fp4inv = readFP4(vector.FP4inv, ctx);

-                a1.copy(fp41);

-                a1.inverse();

-                expect(a1.toString()).to.equal(fp4inv.toString());

-

-                // test multiplication by sqrt(1+sqrt(-1))

-                var fp4mulj = readFP4(vector.FP4mulj, ctx);

-                a1.copy(fp41);

-                a1.times_i();

-                expect(a1.toString()).to.equal(fp4mulj.toString());

-

-                // // test the XTR addition function r=w*x-conj(x)*y+z

-                var fp4xtrA = readFP4(vector.FP4xtrA, ctx);

-                a1.copy(fp42);

-                a1.xtr_A(fp41,fp4add,fp4sub);

-                expect(a1.toString()).to.equal(fp4xtrA.toString());

-

-                // test the XTR addition function r=w*x-conj(x)*y+z

-                var fp4xtrD = readFP4(vector.FP4xtrD, ctx);

-                a1.copy(fp41);

-                a1.xtr_D();

-                expect(a1.toString()).to.equal(fp4xtrD.toString());

-

-                // test the XTR single power r=Tr(x^e)

-                var fp4xtrpow = readFP4(vector.FP4xtrpow, ctx);

-                var fp121 = readFP4(vector.FP121, ctx);

-                a1 = fp121.xtr_pow(BIGsc1);

-                expect(a1.toString()).to.equal(fp4xtrpow.toString());

-

-                // test the XTR double power r=Tr(x^e)

-                var fp4xtrpow2 = readFP4(vector.FP4xtrpow2, ctx);

-                var fp122 = readFP4(vector.FP122, ctx);

-                var fp123 = readFP4(vector.FP123, ctx);

-                var fp124 = readFP4(vector.FP124, ctx);

-                var BIGsc2 = readBIG(vector.BIGsc2, ctx);

-                a1 = fp121.xtr_pow2(fp122,fp123,fp124,BIGsc2,BIGsc1);

-                expect(a1.toString()).to.equal(fp4xtrpow2.toString());

-

-                if (ctx.ECP.AESKEY > 16) {

-                    // Test division by 2

-                    var fp4div2 = readFP4(vector.FP4div2, ctx);

-                    a1.copy(fp41);

-                    a1.div2();

-                    expect(a1.toString()).to.equal(fp4div2.toString());

-

-                    // Test division by i

-                    var fp4divi = readFP4(vector.FP4divi, ctx);

-                    a1.copy(fp41);

-                    a1.div_i();

-                    expect(a1.toString()).to.equal(fp4divi.toString())

-

-                    // Test division by 2i

-                    var fp4div2i = readFP4(vector.FP4div2i, ctx);

-                    a1.copy(fp41);

-                    a1.div_2i();

-                    expect(a1.toString()).to.equal(fp4div2i.toString())

-

-                    // Test square root

-                    var fp4sqrt = readFP4(vector.FP4sqrt, ctx);

-                    a1.copy(fp41);

-                    expect(a1.sqrt()).to.equal(true);

-                    expect(a1).to.satisfy(function(p) {

-                        if(fp4sqrt.toString() === p.toString()) {

-                            return true;

-                        } else {

-                            fp4sqrt.neg();

-                        }

-                        return fp4sqrt.toString() === p.toString();

-                    });

-                }

-            });

-            done();

-        });

-    });

-});

+/*
+    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.
+*/
+
+/* Test FP4 ARITHMETICS - test driver and function exerciser for FP4 API Functions */
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var pf_curves = ['BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'];
+
+var readBIG = function(string, ctx) {
+    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP2 = function(string, ctx) {
+    string = string.split(",");
+    var cox = string[0].slice(1);
+    var coy = string[1].slice(0,-1);
+
+    var x = readBIG(cox,ctx);
+    var y = readBIG(coy,ctx);
+
+    return new ctx.FP2(x,y);;
+}
+
+var readFP4 = function(string, ctx) {
+    var X, Y;
+
+    string = string.split("],[");
+    var cox = string[0].slice(1) + "]";
+    var coy = "[" + string[1].slice(0,-1);
+
+    X = readFP2(cox,ctx);
+    Y = readFP2(coy,ctx);
+
+    return new ctx.FP4(X,Y);
+}
+
+describe('TEST FP4 ARITHMETIC', function() {
+
+    pf_curves.forEach(function(curve){
+
+        it('test '+ curve, function(done) {
+            this.timeout(0);
+
+            var ctx = new CTX(curve);
+            var vectors = require('../testVectors/fp4/'+curve+'.json');
+            var i=0;
+
+            var a1 = new ctx.FP4(1),
+                a2 = new ctx.FP4(0),
+                one = new ctx.FP4(1),
+                zero = new ctx.FP4(0),
+                fp2one = new ctx.FP2(1),
+                fp2zero = new ctx.FP2(0);
+
+            // Test iszilch and isunity
+            expect(zero.iszilch()).to.be.true;
+            expect(one.iszilch()).to.be.false;
+            expect(zero.isunity()).to.be.false;
+            expect(one.isunity()).to.be.true;
+
+            // Test real/isreal
+            expect(one.isreal()).to.be.true;
+            expect(one.real().toString()).to.be.equal(fp2one.toString());
+            one.times_i();
+            expect(one.isreal()).to.be.false;
+            expect(one.real().toString()).to.be.equal(fp2zero.toString());
+
+            // Test set using FP2
+            one.set(fp2one,fp2zero);
+            expect(one.isunity()).to.be.true;
+            one.seta(fp2one);
+            expect(one.isunity()).to.be.true;
+
+            // Test handling sqrt 0,1
+            a1.zero();
+            expect(a1.sqrt()).to.be.true;
+            expect(a1.toString()).to.equal(zero.toString());
+            a1.one();
+            expect(a1.sqrt()).to.be.true;
+            expect(a1.toString()).to.equal(one.toString());
+
+            vectors.forEach(function(vector){
+
+                // test commutativity of addition
+                var fp41 = readFP4(vector.FP41,ctx);
+                var fp42 = readFP4(vector.FP42,ctx);
+                var fp4add = readFP4(vector.FP4add,ctx);
+
+                a1.copy(fp41);
+                a1.add(fp42);
+                expect(a1.toString()).to.equal(fp4add.toString());
+                a2.copy(fp42);
+                a2.add(fp41);
+                expect(a2.toString()).to.equal(fp4add.toString());
+
+                // test associativity of addition
+                a2.add(fp4add);
+                a1.copy(fp41);
+                a1.add(fp4add);
+                a1.add(fp42);
+                expect(a1.toString()).to.equal(a2.toString());
+
+                // test subtraction
+                var fp4sub = readFP4(vector.FP4sub, ctx);
+                a1.copy(fp41);
+                a1.sub(fp42);
+                expect(a1.toString()).to.equal(fp4sub.toString());
+
+                // test negative of a FP4
+                var fp4neg = readFP4(vector.FP4neg, ctx);
+                a1.copy(fp41);
+                a1.neg();
+                expect(a1.toString()).to.equal(fp4neg.toString());
+
+                // test conjugate of a FP4
+                var fp4conj = readFP4(vector.FP4conj, ctx);
+                a1.copy(fp41);
+                a1.conj();
+                expect(a1.toString()).to.equal(fp4conj.toString());
+
+                // test negative conjugate of a FP4
+                var fp4nconj = readFP4(vector.FP4nconj, ctx);
+                a1.copy(fp41);
+                a1.nconj();
+                expect(a1.toString()).to.equal(fp4nconj.toString());
+
+                // test multiplication by FP2
+                var fp4pmul = readFP4(vector.FP4pmul, ctx);
+                var fp2sc = readFP2(vector.FP2sc, ctx);
+                a1.copy(fp41);
+                a1.pmul(fp2sc);
+                expect(a1.toString()).to.equal(fp4pmul.toString());
+
+                // test small scalar multiplication
+                var fp4imul = readFP4(vector.FP4imul, ctx);
+                a1.copy(fp41);
+                a1.imul(i);
+                expect(a1.toString()).to.equal(fp4imul.toString());
+                i++;
+
+                // test square
+                var fp4sqr = readFP4(vector.FP4sqr, ctx);
+                a1.copy(fp41);
+                a1.sqr();
+                expect(a1.toString()).to.equal(fp4sqr.toString());
+
+                // test multiplication
+                var fp4mul = readFP4(vector.FP4mul, ctx);
+                a1.copy(fp41);
+                a1.mul(fp42);
+                expect(a1.toString()).to.equal(fp4mul.toString());
+
+                // test power
+                var fp4pow = readFP4(vector.FP4pow, ctx);
+                var BIGsc1 = readBIG(vector.BIGsc1, ctx);
+                a1 = fp41.pow(BIGsc1);
+                expect(a1.toString()).to.equal(fp4pow.toString());
+
+                // test inverse
+                var fp4inv = readFP4(vector.FP4inv, ctx);
+                a1.copy(fp41);
+                a1.inverse();
+                expect(a1.toString()).to.equal(fp4inv.toString());
+
+                // test multiplication by sqrt(1+sqrt(-1))
+                var fp4mulj = readFP4(vector.FP4mulj, ctx);
+                a1.copy(fp41);
+                a1.times_i();
+                expect(a1.toString()).to.equal(fp4mulj.toString());
+
+                // // test the XTR addition function r=w*x-conj(x)*y+z
+                var fp4xtrA = readFP4(vector.FP4xtrA, ctx);
+                a1.copy(fp42);
+                a1.xtr_A(fp41,fp4add,fp4sub);
+                expect(a1.toString()).to.equal(fp4xtrA.toString());
+
+                // test the XTR addition function r=w*x-conj(x)*y+z
+                var fp4xtrD = readFP4(vector.FP4xtrD, ctx);
+                a1.copy(fp41);
+                a1.xtr_D();
+                expect(a1.toString()).to.equal(fp4xtrD.toString());
+
+                // test the XTR single power r=Tr(x^e)
+                var fp4xtrpow = readFP4(vector.FP4xtrpow, ctx);
+                var fp121 = readFP4(vector.FP121, ctx);
+                a1 = fp121.xtr_pow(BIGsc1);
+                expect(a1.toString()).to.equal(fp4xtrpow.toString());
+
+                // test the XTR double power r=Tr(x^e)
+                var fp4xtrpow2 = readFP4(vector.FP4xtrpow2, ctx);
+                var fp122 = readFP4(vector.FP122, ctx);
+                var fp123 = readFP4(vector.FP123, ctx);
+                var fp124 = readFP4(vector.FP124, ctx);
+                var BIGsc2 = readBIG(vector.BIGsc2, ctx);
+                a1 = fp121.xtr_pow2(fp122,fp123,fp124,BIGsc2,BIGsc1);
+                expect(a1.toString()).to.equal(fp4xtrpow2.toString());
+
+                if (ctx.ECP.AESKEY > 16) {
+                    // Test division by 2
+                    var fp4div2 = readFP4(vector.FP4div2, ctx);
+                    a1.copy(fp41);
+                    a1.div2();
+                    expect(a1.toString()).to.equal(fp4div2.toString());
+
+                    // Test division by i
+                    var fp4divi = readFP4(vector.FP4divi, ctx);
+                    a1.copy(fp41);
+                    a1.div_i();
+                    expect(a1.toString()).to.equal(fp4divi.toString())
+
+                    // Test division by 2i
+                    var fp4div2i = readFP4(vector.FP4div2i, ctx);
+                    a1.copy(fp41);
+                    a1.div_2i();
+                    expect(a1.toString()).to.equal(fp4div2i.toString())
+
+                    // Test square root
+                    var fp4sqrt = readFP4(vector.FP4sqrt, ctx);
+                    a1.copy(fp41);
+                    expect(a1.sqrt()).to.equal(true);
+                    expect(a1).to.satisfy(function(p) {
+                        if(fp4sqrt.toString() === p.toString()) {
+                            return true;
+                        } else {
+                            fp4sqrt.neg();
+                        }
+                        return fp4sqrt.toString() === p.toString();
+                    });
+                }
+            });
+            done();
+        });
+    });
+});
diff --git a/test/test_FP8_js b/test/test_FP8_js
index a40f2ca..f21313c 100644
--- a/test/test_FP8_js
+++ b/test/test_FP8_js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test FP8 ARITHMETICS - test driver and function exerciser for FP8 API Functions */
 
 var chai = require('chai');
diff --git a/test/test_FP_js b/test/test_FP_js
index eb476f2..3ce5b5b 100644
--- a/test/test_FP_js
+++ b/test/test_FP_js
@@ -1,146 +1,145 @@
-/*

-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.

-*/

-

-

-/* Test FP ARITHMETICS - test driver and function exerciser for FP API Functions */

-

-// Here we test only some curves, but those tests cover all the fields FP.

-

-var chai = require('chai');

-

-var CTX = require("../index");

-

-var expect = chai.expect;

-

-var fp_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'NIST384', 'C41417', 'SECP256K1', 'NIST521', 'NUMS256W',

-    'NUMS256E', 'NUMS384W', 'NUMS512W', 'BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'

-];

-

-var readBIG = function(string, ctx) {

-    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}

-    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));

-}

-

-var readFP = function(string, ctx) {

-    return new ctx.FP(readBIG(string, ctx));

-}

-describe('TEST FP ARITHMETIC', function() {

-

-    fp_curves.forEach(function(curve){

-

-        it('test '+ curve, function(done) {

-            this.timeout(0);

-

-            var ctx = new CTX(curve);

-

-            // Select appropriate field for the curve

-            var  field = ctx.config["FIELD"];

-            if (curve == 'NUMS256E') {

-                field = field+"E";

-            }

-            if (curve == 'NUMS256W') {

-                field = field+"W";

-            }

-

-            var vectors = require('../testVectors/fp/'+field+'.json');

-

-            vectors.forEach(function(vector) {

-

-            	// test commutativity of addition

-                var fp1 = readFP(vector.FP1,ctx);

-                var fp2 = readFP(vector.FP2,ctx);

-                var fpadd = readFP(vector.FPadd,ctx);

-                var a1 = new ctx.FP(0);

-                var a2 = new ctx.FP(0);

-                a1.copy(fp1);

-                a1.add(fp2);

-                expect(a1.toString()).to.equal(fpadd.toString());

-                a2.copy(fp2);

-                a2.add(fp1);

-				expect(a2.toString()).to.equal(fpadd.toString());

-

-				// test associativity of addition

-	            a2.add(fpadd);

-	            a1.copy(fp1);

-                a1.add(fpadd);

-                a1.add(fp2);

-	            expect(a1.toString()).to.equal(a2.toString());

-

-	            // test subtraction

-	            var fpsub = readFP(vector.FPsub, ctx);

-	            a1.copy(fp1);

-	            a1.sub(fp2);

-	            expect(a1.toString()).to.equal(fpsub.toString());

-

-                // test multiplication

-                var fpmul = readFP(vector.FPmulmod, ctx);

-                a1.copy(fp1);

-                a1.mul(fp2);

-                expect(a1.toString()).to.equal(fpmul.toString());

-

-                // test small multiplication

-                var fpimul = readFP(vector.FPsmallmul, ctx);

-                a2.imul(0);

-                expect(a2.iszilch()).to.equal(true);

-                for (var vi = 1; vi <= 10; vi++) {

-                    a1.copy(fp1);

-                    a2.copy(fp1);

-                    a1.imul(vi);

-                    for (var vj = 1; vj < vi; vj++) {

-                        a2.add(fp1);

-                    }

-                    expect(a1.toString()).to.equal(a2.toString());

-                }

-                expect(a1.toString()).to.equal(fpimul.toString());

-

-                // test square

-                var fpsqr = readFP(vector.FPsqr, ctx);

-                a1.copy(fp1);

-                a1.sqr();

-                expect(a1.toString()).to.equal(fpsqr.toString());

-

-                // test negative of a FP

-                var fpneg = readFP(vector.FPneg, ctx);

-                a1.copy(fp1);

-                a1.neg();

-                expect(a1.toString()).to.equal(fpneg.toString());

-

-                // test division by 2

-                var fpdiv2 = readFP(vector.FPdiv2, ctx);

-                a1.copy(fp1);

-                a1.div2();

-                expect(a1.toString()).to.equal(fpdiv2.toString());

-

-                // test inverse

-                var fpinv = readFP(vector.FPinv, ctx);

-                a1.copy(fp1);

-                a1.inverse();

-                expect(a1.toString()).to.equal(fpinv.toString());

-

-                // test power

-                var fppow = readFP(vector.FPexp, ctx);

-                a1.copy(fp1);

-                a2 = readBIG(vector.FP2, ctx);

-                a1 = a1.pow(a2);

-                expect(a1.toString()).to.equal(fppow.toString());

-            });

-            done();

-        });

-    });

+/*
+    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.
+*/
+
+/* Test FP ARITHMETICS - test driver and function exerciser for FP API Functions */
+
+// Here we test only some curves, but those tests cover all the fields FP.
+
+var chai = require('chai');
+
+var CTX = require("../index");
+
+var expect = chai.expect;
+
+var fp_curves = ['ED25519', 'GOLDILOCKS', 'NIST256', 'BRAINPOOL', 'ANSSI', 'HIFIVE', 'NIST384', 'C41417', 'SECP256K1', 'NIST521', 'NUMS256W',
+    'NUMS256E', 'NUMS384W', 'NUMS512W', 'BN254', 'BN254CX', 'BLS381', 'BLS383', 'BLS461', 'FP256BN', 'FP512BN', 'BLS24', 'BLS48'
+];
+
+var readBIG = function(string, ctx) {
+    while (string.length != ctx.BIG.MODBYTES*2){string = "00"+string;}
+    return ctx.BIG.fromBytes(Buffer.from(string, "hex"));
+}
+
+var readFP = function(string, ctx) {
+    return new ctx.FP(readBIG(string, ctx));
+}
+describe('TEST FP ARITHMETIC', function() {
+
+    fp_curves.forEach(function(curve){
+
+        it('test '+ curve, function(done) {
+            this.timeout(0);
+
+            var ctx = new CTX(curve);
+
+            // Select appropriate field for the curve
+            var  field = ctx.config["FIELD"];
+            if (curve == 'NUMS256E') {
+                field = field+"E";
+            }
+            if (curve == 'NUMS256W') {
+                field = field+"W";
+            }
+
+            var vectors = require('../testVectors/fp/'+field+'.json');
+
+            vectors.forEach(function(vector) {
+
+            	// test commutativity of addition
+                var fp1 = readFP(vector.FP1,ctx);
+                var fp2 = readFP(vector.FP2,ctx);
+                var fpadd = readFP(vector.FPadd,ctx);
+                var a1 = new ctx.FP(0);
+                var a2 = new ctx.FP(0);
+                a1.copy(fp1);
+                a1.add(fp2);
+                expect(a1.toString()).to.equal(fpadd.toString());
+                a2.copy(fp2);
+                a2.add(fp1);
+				expect(a2.toString()).to.equal(fpadd.toString());
+
+				// test associativity of addition
+	            a2.add(fpadd);
+	            a1.copy(fp1);
+                a1.add(fpadd);
+                a1.add(fp2);
+	            expect(a1.toString()).to.equal(a2.toString());
+
+	            // test subtraction
+	            var fpsub = readFP(vector.FPsub, ctx);
+	            a1.copy(fp1);
+	            a1.sub(fp2);
+	            expect(a1.toString()).to.equal(fpsub.toString());
+
+                // test multiplication
+                var fpmul = readFP(vector.FPmulmod, ctx);
+                a1.copy(fp1);
+                a1.mul(fp2);
+                expect(a1.toString()).to.equal(fpmul.toString());
+
+                // test small multiplication
+                var fpimul = readFP(vector.FPsmallmul, ctx);
+                a2.imul(0);
+                expect(a2.iszilch()).to.equal(true);
+                for (var vi = 1; vi <= 10; vi++) {
+                    a1.copy(fp1);
+                    a2.copy(fp1);
+                    a1.imul(vi);
+                    for (var vj = 1; vj < vi; vj++) {
+                        a2.add(fp1);
+                    }
+                    expect(a1.toString()).to.equal(a2.toString());
+                }
+                expect(a1.toString()).to.equal(fpimul.toString());
+
+                // test square
+                var fpsqr = readFP(vector.FPsqr, ctx);
+                a1.copy(fp1);
+                a1.sqr();
+                expect(a1.toString()).to.equal(fpsqr.toString());
+
+                // test negative of a FP
+                var fpneg = readFP(vector.FPneg, ctx);
+                a1.copy(fp1);
+                a1.neg();
+                expect(a1.toString()).to.equal(fpneg.toString());
+
+                // test division by 2
+                var fpdiv2 = readFP(vector.FPdiv2, ctx);
+                a1.copy(fp1);
+                a1.div2();
+                expect(a1.toString()).to.equal(fpdiv2.toString());
+
+                // test inverse
+                var fpinv = readFP(vector.FPinv, ctx);
+                a1.copy(fp1);
+                a1.inverse();
+                expect(a1.toString()).to.equal(fpinv.toString());
+
+                // test power
+                var fppow = readFP(vector.FPexp, ctx);
+                a1.copy(fp1);
+                a2 = readBIG(vector.FP2, ctx);
+                a1 = a1.pow(a2);
+                expect(a1.toString()).to.equal(fppow.toString());
+            });
+            done();
+        });
+    });
 });
\ No newline at end of file
diff --git a/test/test_GCM.js b/test/test_GCM.js
index 8d00af5..472cac9 100644
--- a/test/test_GCM.js
+++ b/test/test_GCM.js
@@ -1,23 +1,22 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
-
 /* Test GCM function - test driver and function exerciser for GCM API Functions */
 
 var CTX = require("../index");
@@ -115,4 +114,4 @@
         done();
     });
 
-});
\ No newline at end of file
+});
diff --git a/test/test_HASH.js b/test/test_HASH.js
index 8b03389..b9219d7 100644
--- a/test/test_HASH.js
+++ b/test/test_HASH.js
@@ -1,128 +1,127 @@
-/*

-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.

-*/

-

-

-/* Test HASH function - test driver and function exerciser for SHA256, SHA384, SHA512 API Functions */

-

-var CTX = require("../index");

-

-var chai = require('chai');

-

-var expect = chai.expect;

-

-var ctx = new CTX();

-

-

-var bytestostring = function(b) {

-    var s = "";

-    var len = b.length;

-    var ch;

-

-    for (var i = 0; i < len; i++) {

-        ch = b[i];

-        s += ((ch >>> 4) & 15).toString(16);

-        s += (ch & 15).toString(16);

-    }

-    return s;

-}

-

-var stringtobytes = function(s) {

-    var b = [];

-    for (var i = 0; i < s.length; i++)

-        b.push(s.charCodeAt(i));

-    return b;

-}

-

-hextobytes = function(value_hex) {

-    // "use strict";

-    var len, byte_value, i;

-

-    len = value_hex.length;

-    byte_value = [];

-

-    for (i = 0; i < len; i += 2) {

-        byte_value[(i / 2)] = parseInt(value_hex.substr(i, 2), 16);

-    }

-    return byte_value;

-};

-

-var hashit = function(sha, B) {

-    var R = [];

-

-    if (sha == ctx.HASH256.len) {

-        var H = new ctx.HASH256();

-        H.process_array(B);

-        R = H.hash();

-    }

-    else if (sha == ctx.HASH384.len) {

-        var H = new ctx.HASH384();

-        H.process_array(B);

-        R = H.hash();

-    }

-    else if (sha == ctx.HASH512.len) {

-        var H = new ctx.HASH512();

-        H.process_array(B);

-        R = H.hash();

-    }

-    if (R.length == 0) return null;

-    return R;

-}

-

-describe('TEST HASH', function() {

-

-    it('test SHA256', function(done) {

-        this.timeout(0);

-

-        var vectors = require('../testVectors/sha/SHA256.json');

-        var dig;

-

-        for (var vector in vectors) {

-            dig = hashit(ctx.HASH256.len, hextobytes(vectors[vector].IN));

-            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);

-        }

-        done();

-    });

-

-    it('test SHA384', function(done) {

-        this.timeout(0);

-

-        var vectors = require('../testVectors/sha/SHA384.json');

-        var dig;

-

-        for (var vector in vectors) {

-            dig = hashit(ctx.HASH384.len, hextobytes(vectors[vector].IN));

-            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);

-        }

-        done();

-    });

-

-    it('test SHA512', function(done) {

-        this.timeout(0);

-

-        var vectors = require('../testVectors/sha/SHA512.json');

-        var dig;

-

-        for (var vector in vectors) {

-            dig = hashit(ctx.HASH512.len, hextobytes(vectors[vector].IN));

-            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);

-        }

-        done();

-    });

-

-});
\ No newline at end of file
+/*
+    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.
+*/
+
+/* Test HASH function - test driver and function exerciser for SHA256, SHA384, SHA512 API Functions */
+
+var CTX = require("../index");
+
+var chai = require('chai');
+
+var expect = chai.expect;
+
+var ctx = new CTX();
+
+
+var bytestostring = function(b) {
+    var s = "";
+    var len = b.length;
+    var ch;
+
+    for (var i = 0; i < len; i++) {
+        ch = b[i];
+        s += ((ch >>> 4) & 15).toString(16);
+        s += (ch & 15).toString(16);
+    }
+    return s;
+}
+
+var stringtobytes = function(s) {
+    var b = [];
+    for (var i = 0; i < s.length; i++)
+        b.push(s.charCodeAt(i));
+    return b;
+}
+
+hextobytes = function(value_hex) {
+    // "use strict";
+    var len, byte_value, i;
+
+    len = value_hex.length;
+    byte_value = [];
+
+    for (i = 0; i < len; i += 2) {
+        byte_value[(i / 2)] = parseInt(value_hex.substr(i, 2), 16);
+    }
+    return byte_value;
+};
+
+var hashit = function(sha, B) {
+    var R = [];
+
+    if (sha == ctx.HASH256.len) {
+        var H = new ctx.HASH256();
+        H.process_array(B);
+        R = H.hash();
+    }
+    else if (sha == ctx.HASH384.len) {
+        var H = new ctx.HASH384();
+        H.process_array(B);
+        R = H.hash();
+    }
+    else if (sha == ctx.HASH512.len) {
+        var H = new ctx.HASH512();
+        H.process_array(B);
+        R = H.hash();
+    }
+    if (R.length == 0) return null;
+    return R;
+}
+
+describe('TEST HASH', function() {
+
+    it('test SHA256', function(done) {
+        this.timeout(0);
+
+        var vectors = require('../testVectors/sha/SHA256.json');
+        var dig;
+
+        for (var vector in vectors) {
+            dig = hashit(ctx.HASH256.len, hextobytes(vectors[vector].IN));
+            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);
+        }
+        done();
+    });
+
+    it('test SHA384', function(done) {
+        this.timeout(0);
+
+        var vectors = require('../testVectors/sha/SHA384.json');
+        var dig;
+
+        for (var vector in vectors) {
+            dig = hashit(ctx.HASH384.len, hextobytes(vectors[vector].IN));
+            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);
+        }
+        done();
+    });
+
+    it('test SHA512', function(done) {
+        this.timeout(0);
+
+        var vectors = require('../testVectors/sha/SHA512.json');
+        var dig;
+
+        for (var vector in vectors) {
+            dig = hashit(ctx.HASH512.len, hextobytes(vectors[vector].IN));
+            expect(bytestostring(dig)).to.be.equal(vectors[vector].OUT);
+        }
+        done();
+    });
+
+});
diff --git a/test/test_MPIN.js b/test/test_MPIN.js
index 308474c..164d9dc 100644
--- a/test/test_MPIN.js
+++ b/test/test_MPIN.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test MPIN - test driver and function exerciser for MPIN API Functions */
diff --git a/test/test_PAIR.js b/test/test_PAIR.js
index b56c187..d194750 100644
--- a/test/test_PAIR.js
+++ b/test/test_PAIR.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test MPIN - test driver and function exerciser for MPIN API Functions */
diff --git a/test/test_RSA2048.js b/test/test_RSA2048.js
index 27aab32..af1ba9a 100644
--- a/test/test_RSA2048.js
+++ b/test/test_RSA2048.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test RSA - test driver and function exerciser for RSA API Functions */
diff --git a/test/test_RSA3072.js b/test/test_RSA3072.js
index 5e96e21..b35b0d5 100644
--- a/test/test_RSA3072.js
+++ b/test/test_RSA3072.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test RSA - test driver and function exerciser for RSA API Functions */
diff --git a/test/test_RSA4096.js b/test/test_RSA4096.js
index add8fd1..4869abf 100644
--- a/test/test_RSA4096.js
+++ b/test/test_RSA4096.js
@@ -1,20 +1,20 @@
 /*
-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
+    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
+    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.
+    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.
 */
 
 /* Test RSA - test driver and function exerciser for RSA API Functions */