2 // System.Security.Cryptography.ToBase64Transform
5 // Sergey Chaban (serge@wildwestsoftware.com)
7 // (C) 2004 Novell (http://www.novell.com)
11 using System.Globalization;
13 namespace System.Security.Cryptography {
15 public class ToBase64Transform : ICryptoTransform {
17 private bool m_disposed;
19 public ToBase64Transform ()
28 public bool CanTransformMultipleBlocks {
32 public virtual bool CanReuseTransform {
36 public int InputBlockSize {
40 public int OutputBlockSize {
49 void IDisposable.Dispose ()
52 GC.SuppressFinalize (this); // Finalization is now unnecessary
55 protected virtual void Dispose (bool disposing)
58 // dispose unmanaged objects
60 // dispose managed objects
66 // LAMESPEC: It's not clear from docs what should be happening
67 // here if inputCount > InputBlockSize. It just "Converts the
68 // specified region of the specified byte array" and that's all.
69 public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
72 throw new ObjectDisposedException ("TransformBlock");
73 if (inputBuffer == null)
74 throw new ArgumentNullException ("inputBuffer");
75 if (outputBuffer == null)
76 throw new ArgumentNullException ("outputBuffer");
78 throw new ArgumentException ("inputCount", "< 0");
79 if (inputCount > inputBuffer.Length)
80 throw new ArgumentException ("inputCount", Locale.GetText ("Overflow"));
82 throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
83 // ordered to avoid possible integer overflow
84 if (inputOffset > inputBuffer.Length - inputCount)
85 throw new ArgumentException ("inputOffset", Locale.GetText ("Overflow"));
86 // ordered to avoid possible integer overflow
87 if ((outputOffset < 0) || (outputOffset > outputBuffer.Length - inputCount))
88 throw new IndexOutOfRangeException ("outputOffset");
89 /// To match MS implementation
90 // if (inputCount != this.InputBlockSize)
91 // throw new CryptographicException (Locale.GetText ("Invalid input length"));
93 byte[] lookup = Base64Constants.EncodeTable;
95 int b1 = inputBuffer [inputOffset];
96 int b2 = inputBuffer [inputOffset + 1];
97 int b3 = inputBuffer [inputOffset + 2];
99 outputBuffer [outputOffset] = lookup [b1 >> 2];
100 outputBuffer [outputOffset+1] = lookup [((b1 << 4) & 0x30) | (b2 >> 4)];
101 outputBuffer [outputOffset+2] = lookup [((b2 << 2) & 0x3c) | (b3 >> 6)];
102 outputBuffer [outputOffset+3] = lookup [b3 & 0x3f];
104 return this.OutputBlockSize;
107 public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
110 throw new ObjectDisposedException ("TransformFinalBlock");
111 if (inputBuffer == null)
112 throw new ArgumentNullException ("inputBuffer");
114 throw new ArgumentException ("inputCount", "< 0");
115 if (inputOffset > inputBuffer.Length - inputCount)
116 throw new ArgumentException ("inputCount", Locale.GetText ("Overflow"));
117 if (inputCount > this.InputBlockSize)
118 throw new ArgumentOutOfRangeException (Locale.GetText ("Invalid input length"));
120 return InternalTransformFinalBlock (inputBuffer, inputOffset, inputCount);
123 // Mono System.Convert depends on the ability to process multiple blocks
124 internal byte[] InternalTransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
126 int blockLen = this.InputBlockSize;
127 int outLen = this.OutputBlockSize;
128 int fullBlocks = inputCount / blockLen;
129 int tail = inputCount % blockLen;
131 byte[] res = new byte [(inputCount != 0)
132 ? ((inputCount + 2) / blockLen) * outLen
135 int outputOffset = 0;
137 for (int i = 0; i < fullBlocks; i++) {
139 TransformBlock (inputBuffer, inputOffset,
140 blockLen, res, outputOffset);
142 inputOffset += blockLen;
143 outputOffset += outLen;
146 byte[] lookup = Base64Constants.EncodeTable;
149 // When fewer than 24 input bits are available
150 // in an input group, zero bits are added
151 // (on the right) to form an integral number of
157 b1 = inputBuffer [inputOffset];
158 res [outputOffset] = lookup [b1 >> 2];
159 res [outputOffset+1] = lookup [(b1 << 4) & 0x30];
162 res [outputOffset+2] = (byte)'=';
163 res [outputOffset+3] = (byte)'=';
167 b1 = inputBuffer [inputOffset];
168 b2 = inputBuffer [inputOffset + 1];
169 res [outputOffset] = lookup [b1 >> 2];
170 res [outputOffset+1] = lookup [((b1 << 4) & 0x30) | (b2 >> 4)];
171 res [outputOffset+2] = lookup [(b2 << 2) & 0x3c];
174 res [outputOffset+3] = (byte)'=';