add JavaScript markdown documentation
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>