summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2020-07-30 18:54:46 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2020-07-30 18:54:46 +0700
commit6df85c63349e5a0ddc9187de8779443fa8b55963 (patch)
treec3cca3d575f452ae9d96cdf8880a9610e1af4866
parentAdd generic private key output to openssl (diff)
downloadBouncyCastle.NET-ed25519-6df85c63349e5a0ddc9187de8779443fa8b55963.tar.xz
Encoder performance
-rw-r--r--crypto/src/util/encoders/Base64Encoder.cs162
-rw-r--r--crypto/src/util/encoders/HexEncoder.cs75
2 files changed, 155 insertions, 82 deletions
diff --git a/crypto/src/util/encoders/Base64Encoder.cs b/crypto/src/util/encoders/Base64Encoder.cs
index 07294c9a6..21e8051d3 100644
--- a/crypto/src/util/encoders/Base64Encoder.cs
+++ b/crypto/src/util/encoders/Base64Encoder.cs
@@ -44,69 +44,69 @@ namespace Org.BouncyCastle.Utilities.Encoders
             InitialiseDecodingTable();
         }
 
-        /**
-        * encode the input data producing a base 64 output stream.
-        *
-        * @return the number of bytes produced.
-        */
-        public int Encode(
-            byte[]	data,
-            int		off,
-            int		length,
-            Stream	outStream)
+        public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
         {
-            int modulus = length % 3;
-            int dataLength = (length - modulus);
-            int a1, a2, a3;
+            int inPos = inOff;
+            int inEnd = inOff + inLen - 2;
+            int outPos = outOff;
 
-            for (int i = off; i < off + dataLength; i += 3)
+            while (inPos < inEnd)
             {
-                a1 = data[i] & 0xff;
-                a2 = data[i + 1] & 0xff;
-                a3 = data[i + 2] & 0xff;
-
-                outStream.WriteByte(encodingTable[(int) ((uint) a1 >> 2) & 0x3f]);
-                outStream.WriteByte(encodingTable[((a1 << 4) | (int) ((uint) a2 >> 4)) & 0x3f]);
-                outStream.WriteByte(encodingTable[((a2 << 2) | (int) ((uint) a3 >> 6)) & 0x3f]);
-                outStream.WriteByte(encodingTable[a3 & 0x3f]);
+                uint a1 = inBuf[inPos++];
+                uint a2 = inBuf[inPos++];
+                uint a3 = inBuf[inPos++];
+
+                outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
+                outBuf[outPos++] = encodingTable[((a1 << 4) | (a2 >> 4)) & 0x3F];
+                outBuf[outPos++] = encodingTable[((a2 << 2) | (a3 >> 6)) & 0x3F];
+                outBuf[outPos++] = encodingTable[a3 & 0x3F];
             }
 
-            /*
-            * process the tail end.
-            */
-            int b1, b2, b3;
-            int d1, d2;
+            switch (inLen - (inPos - inOff))
+            {
+            case 1:
+            {
+                uint a1 = inBuf[inPos++];
 
-            switch (modulus)
+                outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
+                outBuf[outPos++] = encodingTable[(a1 << 4) & 0x3F];
+                outBuf[outPos++] = padding;
+                outBuf[outPos++] = padding;
+                break;
+            }
+            case 2:
             {
-                case 0:        /* nothing left to do */
-                    break;
-                case 1:
-                    d1 = data[off + dataLength] & 0xff;
-                    b1 = (d1 >> 2) & 0x3f;
-                    b2 = (d1 << 4) & 0x3f;
-
-                    outStream.WriteByte(encodingTable[b1]);
-                    outStream.WriteByte(encodingTable[b2]);
-                    outStream.WriteByte(padding);
-                    outStream.WriteByte(padding);
-                    break;
-                case 2:
-                    d1 = data[off + dataLength] & 0xff;
-                    d2 = data[off + dataLength + 1] & 0xff;
-
-                    b1 = (d1 >> 2) & 0x3f;
-                    b2 = ((d1 << 4) | (d2 >> 4)) & 0x3f;
-                    b3 = (d2 << 2) & 0x3f;
-
-                    outStream.WriteByte(encodingTable[b1]);
-                    outStream.WriteByte(encodingTable[b2]);
-                    outStream.WriteByte(encodingTable[b3]);
-                    outStream.WriteByte(padding);
-                    break;
+                uint a1 = inBuf[inPos++];
+                uint a2 = inBuf[inPos++];
+
+                outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
+                outBuf[outPos++] = encodingTable[((a1 << 4) | (a2 >> 4)) & 0x3F];
+                outBuf[outPos++] = encodingTable[(a2 << 2) & 0x3F];
+                outBuf[outPos++] = padding;
+                break;
             }
+            }
+
+            return outPos - outOff;
+        }
 
-            return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
+        /**
+        * encode the input data producing a base 64 output stream.
+        *
+        * @return the number of bytes produced.
+        */
+        public int Encode(byte[] buf, int off, int len, Stream outStream) 
+        {
+            byte[] tmp = new byte[72];
+            while (len > 0)
+            {
+                int inLen = System.Math.Min(54, len);
+                int outLen = Encode(buf, off, inLen, tmp, 0);
+                outStream.Write(tmp, 0, outLen);
+                off += inLen;
+                len -= inLen;
+            }
+            return ((len + 2) / 3) * 4;
         }
 
         private bool ignore(
@@ -128,8 +128,9 @@ namespace Org.BouncyCastle.Utilities.Encoders
             Stream	outStream)
         {
             byte b1, b2, b3, b4;
+            byte[] outBuffer = new byte[54];   // S/MIME standard
+            int bufOff = 0;
             int outLen = 0;
-
             int end = off + length;
 
             while (end > off)
@@ -166,16 +167,32 @@ namespace Org.BouncyCastle.Utilities.Encoders
                 if ((b1 | b2 | b3 | b4) >= 0x80)
                     throw new IOException("invalid characters encountered in base64 data");
 
-                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
-                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
-                outStream.WriteByte((byte)((b3 << 6) | b4));
+                outBuffer[bufOff++] = (byte)((b1 << 2) | (b2 >> 4));
+                outBuffer[bufOff++] = (byte)((b2 << 4) | (b3 >> 2));
+                outBuffer[bufOff++] = (byte)((b3 << 6) | b4);
+
+                if (bufOff == outBuffer.Length)
+                {
+                    outStream.Write(outBuffer, 0, bufOff);
+                    bufOff = 0;
+                }
 
                 outLen += 3;
 
                 i = nextI(data, i, finish);
             }
 
-            outLen += decodeLastBlock(outStream, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
+            if (bufOff > 0)
+            {
+                outStream.Write(outBuffer, 0, bufOff);
+            }
+
+            int e0 = nextI(data, i, end);
+            int e1 = nextI(data, e0 + 1, end);
+            int e2 = nextI(data, e1 + 1, end);
+            int e3 = nextI(data, e2 + 1, end);
+
+            outLen += decodeLastBlock(outStream, (char)data[e0], (char)data[e1], (char)data[e2], (char)data[e3]);
 
             return outLen;
         }
@@ -208,8 +225,9 @@ namespace Org.BouncyCastle.Utilities.Encoders
 //			return bytes.Length;
 
             byte b1, b2, b3, b4;
+            byte[] outBuffer = new byte[54];   // S/MIME standard
+            int bufOff = 0;
             int length = 0;
-
             int end = data.Length;
 
             while (end > 0)
@@ -246,16 +264,32 @@ namespace Org.BouncyCastle.Utilities.Encoders
                 if ((b1 | b2 | b3 | b4) >= 0x80)
                     throw new IOException("invalid characters encountered in base64 data");
 
-                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
-                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
-                outStream.WriteByte((byte)((b3 << 6) | b4));
+                outBuffer[bufOff++] = (byte)((b1 << 2) | (b2 >> 4));
+                outBuffer[bufOff++] = (byte)((b2 << 4) | (b3 >> 2));
+                outBuffer[bufOff++] = (byte)((b3 << 6) | b4);
 
                 length += 3;
 
+                if (bufOff == outBuffer.Length)
+                {
+                    outStream.Write(outBuffer, 0, bufOff);
+                    bufOff = 0;
+                }
+
                 i = nextI(data, i, finish);
             }
 
-            length += decodeLastBlock(outStream, data[end - 4], data[end - 3], data[end - 2], data[end - 1]);
+            if (bufOff > 0)
+            {
+                outStream.Write(outBuffer, 0, bufOff);
+            }
+
+            int e0 = nextI(data, i, end);
+            int e1 = nextI(data, e0 + 1, end);
+            int e2 = nextI(data, e1 + 1, end);
+            int e3 = nextI(data, e2 + 1, end);
+
+            length += decodeLastBlock(outStream, data[e0], data[e1], data[e2], data[e3]);
 
             return length;
         }
diff --git a/crypto/src/util/encoders/HexEncoder.cs b/crypto/src/util/encoders/HexEncoder.cs
index 950bc8477..090c9d7e3 100644
--- a/crypto/src/util/encoders/HexEncoder.cs
+++ b/crypto/src/util/encoders/HexEncoder.cs
@@ -39,26 +39,40 @@ namespace Org.BouncyCastle.Utilities.Encoders
             InitialiseDecodingTable();
         }
 
+        public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
+        {
+            int inPos = inOff;
+            int inEnd = inOff + inLen;
+            int outPos = outOff;
+
+            while (inPos < inEnd)
+            {
+                uint b = inBuf[inPos++];
+
+                outBuf[outPos++] = encodingTable[b >> 4];
+                outBuf[outPos++] = encodingTable[b & 0xF];
+            }
+
+            return outPos - outOff;
+        }
+
         /**
         * encode the input data producing a Hex output stream.
         *
         * @return the number of bytes produced.
         */
-        public int Encode(
-            byte[]	data,
-            int		off,
-            int		length,
-            Stream	outStream)
+        public int Encode(byte[] buf, int off, int len, Stream outStream)
         {
-            for (int i = off; i < (off + length); i++)
+            byte[] tmp = new byte[72];
+            while (len > 0)
             {
-                int v = data[i];
-
-                outStream.WriteByte(encodingTable[v >> 4]);
-                outStream.WriteByte(encodingTable[v & 0xf]);
+                int inLen = System.Math.Min(36, len);
+                int outLen = Encode(buf, off, inLen, tmp, 0);
+                outStream.Write(tmp, 0, outLen);
+                off += inLen;
+                len -= inLen;
             }
-
-            return length * 2;
+            return len * 2;
         }
 
         private static bool Ignore(char c)
@@ -80,6 +94,8 @@ namespace Org.BouncyCastle.Utilities.Encoders
         {
             byte b1, b2;
             int outLen = 0;
+            byte[] buf = new byte[36];
+            int bufOff = 0;
             int end = off + length;
 
             while (end > off)
@@ -112,11 +128,22 @@ namespace Org.BouncyCastle.Utilities.Encoders
                 if ((b1 | b2) >= 0x80)
                     throw new IOException("invalid characters encountered in Hex data");
 
-                outStream.WriteByte((byte)((b1 << 4) | b2));
+                buf[bufOff++] = (byte)((b1 << 4) | b2);
+
+                if (bufOff == buf.Length)
+                {
+                    outStream.Write(buf, 0, bufOff);
+                    bufOff = 0;
+                }
 
                 outLen++;
             }
 
+            if (bufOff > 0)
+            {
+                outStream.Write(buf, 0, bufOff);
+            }
+
             return outLen;
         }
 
@@ -130,10 +157,11 @@ namespace Org.BouncyCastle.Utilities.Encoders
             string	data,
             Stream	outStream)
         {
-            byte    b1, b2;
-            int     length = 0;
-
-            int     end = data.Length;
+            byte b1, b2;
+            int length = 0;
+            byte[] buf = new byte[36];
+            int bufOff = 0;
+            int end = data.Length;
 
             while (end > 0)
             {
@@ -165,11 +193,22 @@ namespace Org.BouncyCastle.Utilities.Encoders
                 if ((b1 | b2) >= 0x80)
                     throw new IOException("invalid characters encountered in Hex data");
 
-                outStream.WriteByte((byte)((b1 << 4) | b2));
+                buf[bufOff++] = (byte)((b1 << 4) | b2);
+
+                if (bufOff == buf.Length)
+                {
+                    outStream.Write(buf, 0, bufOff);
+                    bufOff = 0;
+                }
 
                 length++;
             }
 
+            if (bufOff > 0)
+            {
+                outStream.Write(buf, 0, bufOff);
+            }
+
             return length;
         }