package org.bouncycastle.crypto.modes.gcm;

import org.bouncycastle.util.Arrays;

public class Tables1kGCMExponentiator implements GCMExponentiator
{
    // A lookup table of the power-of-two powers of 'x'
    byte[][] lookupPowX2 = new byte[64][];

    public void init(byte[] x)
    {
        lookupPowX2[0] = GCMUtil.oneAsBytes();
        lookupPowX2[1] = Arrays.clone(x); 

        for (int i = 2; i != 64; ++i)
        {
            byte[] tmp = Arrays.clone(lookupPowX2[i - 1]);
            GCMUtil.multiply(tmp, tmp);
            lookupPowX2[i] = tmp;
        }
    }

    public void exponentiateX(long pow, byte[] output)
    {
        byte[] y = GCMUtil.oneAsBytes();
        int powX2 = 1;

        while (pow > 0)
        {
            if ((pow & 1L) != 0)
            {
                GCMUtil.multiply(y, lookupPowX2[powX2]);
            }
            ++powX2;
            pow >>>= 1;
        }

        System.arraycopy(y, 0, output, 0, 16);
    }
}

@@ -199,24 +199,72 @@
  of 'x'%0A    
+// - lookupPowX2%5Bi%5D = x%5E(2%5Ei)%0A    private final 
 byte%5B%5D%5B%5D loo
@@ -291,16 +291,52 @@
 64%5D%5B%5D;%0A%0A
+    private int highestIndex = -1;%0A%0A
     publ
@@ -376,89 +376,87 @@
     
-lookupPowX2%5B0%5D = GCMUtil.oneAsBytes();%0A        lookupPowX2%5B1%5D = Arrays.clone(x); 
+if (Arrays.areEqual(x, lookupPowX2%5B0%5D))%0A        %7B%0A            return;%0A        %7D
 %0A%0A  
@@ -478,18 +478,28 @@
 i = 
-2
+1
 ; i 
-!= 64
+%3C= highestIndex
 ; ++
@@ -527,34 +527,8 @@
     
-byte%5B%5D tmp = Arrays.clone(
 look
@@ -540,14 +540,16 @@
 X2%5Bi
- - 1%5D)
+%5D = null
 ;%0A  
@@ -558,44 +558,11 @@
     
-    GCMUtil.multiply(tmp, tmp);%0A    
+%7D%0A%0A
     
@@ -581,27 +581,55 @@
 wX2%5B
-i
+0
 %5D = 
-tmp;%0A        %7D
+Arrays.clone(x);%0A        highestIndex = 0;
 %0A   
@@ -747,31 +747,67 @@
    i
-nt powX2 = 1;%0A%0A
+f (pow %3E 0)%0A        %7B%0A            int bit = 0;%0A    
         
 whil
@@ -806,32 +806,89 @@
     
-while (pow %3E 0)%0A
+ensureAvailable(63 - Long.numberOfLeadingZeros(pow));%0A%0A            do%0A   
         
 %7B%0A  
@@ -875,34 +875,39 @@
   do%0A           
+ 
 %7B%0A
+    
             if (
@@ -927,34 +927,42 @@
  0)%0A            
-%7B%0A
+    %7B%0A    
                 
@@ -997,17 +997,19 @@
 wX2%5B
-powX2%5D);%0A
+bit%5D);%0A    
     
@@ -1034,17 +1034,23 @@
     
-++powX2;%0A
+    ++bit;%0A    
     
@@ -1069,16 +1069,59 @@
 %3E%3E%3E= 1;%0A
+            %7D%0A            while (pow %3E 0);%0A
         
@@ -1175,11 +1175,268 @@
 );%0A    %7D
+%0A%0A    private void ensureAvailable(int bit)%0A    %7B%0A        while (highestIndex %3C bit)%0A        %7B%0A          byte%5B%5D tmp = Arrays.clone(lookupPowX2%5BhighestIndex%5D);%0A          GCMUtil.multiply(tmp, tmp);%0A          lookupPowX2%5B++highestIndex%5D = tmp;%0A        %7D%0A    %7D
 %0A%7D%0A

Generate the table lazily