| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- //
- // System.Security.Cryptography.FromBase64Transform
- //
- // Author:
- // Sergey Chaban ([email protected])
- //
- using System;
- using System.Security.Cryptography;
- namespace System.Security.Cryptography {
- public enum FromBase64TransformMode : int {
- IgnoreWhiteSpaces,
- DoNotIgnoreWhiteSpaces
- }
- public class FromBase64Transform : ICryptoTransform {
- private FromBase64TransformMode mode;
- private byte [] accumulator;
- private byte [] filterBuffer;
- private int accPtr;
- /// <summary>
- /// Creates a new instance of the decoder
- /// with the default transformation mode (IgnoreWhiteSpaces).
- /// </summary>
- public FromBase64Transform ()
- : this (FromBase64TransformMode.IgnoreWhiteSpaces)
- {
- }
- /// <summary>
- /// Creates a new instance of the decoder
- /// with the specified transformation mode.
- /// </summary>
- public FromBase64Transform (FromBase64TransformMode mode)
- {
- this.mode = mode;
- accumulator = new byte [4];
- filterBuffer = new byte [4];
- accPtr = 0;
- }
- /// <summary>
- /// </summary>
- public virtual bool CanTransformMultipleBlocks {
- get {
- return false;
- }
- }
- /// <summary>
- /// Returns the input block size for the Base64 decoder.
- /// </summary>
- /// <remarks>
- /// The input block size for Base64 decoder is always 1 byte.
- /// </remarks>
- public virtual int InputBlockSize {
- get {
- return 1;
- }
- }
- /// <summary>
- /// Returns the output block size for the Base64 decoder.
- /// </summary>
- /// <remarks>
- /// The value returned by this property is always 3.
- /// </remarks>
- public virtual int OutputBlockSize {
- get {
- return 3;
- }
- }
- private int Filter (byte [] buffer, int offset, int count)
- {
- int end = offset + count;
- int len = filterBuffer.Length;
- int ptr = 0;
- byte [] filter = this.filterBuffer;
- for (int i = offset; i < end; i++) {
- byte b = buffer [i];
- if (!Char.IsWhiteSpace ((char) b)) {
- if (ptr >= len) {
- len <<= 1;
- this.filterBuffer = new byte [len];
- Array.Copy(filter, 0, this.filterBuffer, 0, len >> 1);
- filter = this.filterBuffer;
- }
- filter [ptr++] = b;
- }
- }
- return ptr;
- }
- private int DoTransform (byte [] inputBuffer,
- int inputOffset,
- int inputCount,
- byte [] outputBuffer,
- int outputOffset)
- {
- int full = inputCount >> 2;
- if (full == 0) return 0;
- int rem = 0;
- if (inputBuffer[inputCount - 1] == (byte)'=') {
- ++rem;
- --full;
- }
- if (inputBuffer[inputCount - 2] == (byte)'=') ++rem;
- byte [] lookup = Base64Table.DecodeTable;
- int b0,b1,b2,b3;
- for (int i = 0; i < full; i++) {
- b0 = lookup [inputBuffer [inputOffset++]];
- b1 = lookup [inputBuffer [inputOffset++]];
- b2 = lookup [inputBuffer [inputOffset++]];
- b3 = lookup [inputBuffer [inputOffset++]];
- outputBuffer [outputOffset++] = (byte) ((b0 << 2) | (b1 >> 4));
- outputBuffer [outputOffset++] = (byte) ((b1 << 4) | (b2 >> 2));
- outputBuffer [outputOffset++] = (byte) ((b2 << 6) | b3);
- }
- int res = full * 3;
- switch (rem) {
- case 0:
- break;
- case 1:
- b0 = lookup [inputBuffer [inputOffset++]];
- b1 = lookup [inputBuffer [inputOffset++]];
- b2 = lookup [inputBuffer [inputOffset++]];
- outputBuffer [outputOffset++] = (byte) ((b0 << 2) | (b1 >> 4));
- outputBuffer [outputOffset++] = (byte) ((b1 << 4) | (b2 >> 2));
- res += 2;
- break;
- case 2:
- b0 = lookup [inputBuffer [inputOffset++]];
- b1 = lookup [inputBuffer [inputOffset++]];
- outputBuffer [outputOffset++] = (byte) ((b0 << 2) | (b1 >> 4));
- ++res;
- break;
- default:
- break;
- }
- return res;
- }
- /// <summary>
- /// </summary>
- public virtual int TransformBlock (byte [] inputBuffer,
- int inputOffset,
- int inputCount,
- byte [] outputBuffer,
- int outputOffset)
- {
- int n;
- byte [] src;
- int srcOff;
- int res = 0;
- if (mode == FromBase64TransformMode.IgnoreWhiteSpaces) {
- n = Filter (inputBuffer, inputOffset, inputCount);
- src = filterBuffer;
- srcOff = 0;
- } else {
- n = inputCount;
- src = inputBuffer;
- srcOff = inputOffset;
- }
- int count = accPtr + n;
- if (count < 4) {
- Array.Copy (src, srcOff, accumulator, accPtr, n);
- accPtr = count;
- } else {
- byte [] tmpBuff = new byte [count];
- Array.Copy (accumulator, 0, tmpBuff, 0, accPtr);
- Array.Copy (src, srcOff, tmpBuff, accPtr, n);
- accPtr = count & 3;
- Array.Copy (src, srcOff + (n - accPtr), accumulator, 0, accPtr);
- res = DoTransform (tmpBuff, 0, count & (~3), outputBuffer, outputOffset);
- }
- return res;
- }
- /// <summary>
- /// </summary>
- public virtual byte [] TransformFinalBlock (byte [] inputBuffer,
- int inputOffset,
- int inputCount)
- {
- byte [] src;
- int srcOff;
- int n;
- if (mode == FromBase64TransformMode.IgnoreWhiteSpaces) {
- n = Filter (inputBuffer, inputOffset, inputCount);
- src = filterBuffer;
- srcOff = 0;
- } else {
- n = inputCount;
- src = inputBuffer;
- srcOff = inputOffset;
- }
- int dataLen = accPtr + n;
- byte [] tmpBuf = new byte [dataLen];
- int resLen = ((dataLen) >> 2) * 3;
- byte [] res = new byte [resLen];
- Array.Copy (accumulator, 0, tmpBuf, 0, accPtr);
- Array.Copy (src, srcOff, tmpBuf, accPtr, n);
- DoTransform (tmpBuf, 0, dataLen, res, 0);
- accPtr = 0;
- return res;
- }
- /// <summary>
- /// </summary>
- public override string ToString ()
- {
- return "mono::System.Security.Cryptography.FromBase64Transform";
- }
- } // FromBase64Transform
- } // System.Security.Cryptography
|