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;
20 /// Default constructor.
22 public ToBase64Transform ()
26 /* Right now we have nothing to dispose to finalizer isn't required
32 public bool CanTransformMultipleBlocks {
36 public virtual bool CanReuseTransform {
41 /// Returns the input block size for the Base64 encoder.
44 /// The returned value is always 3.
46 public int InputBlockSize {
51 /// Returns the output block size for the Base64 encoder.
54 /// The value returned by this property is always 4.
56 public int OutputBlockSize {
65 void IDisposable.Dispose ()
68 GC.SuppressFinalize (this); // Finalization is now unnecessary
71 protected virtual void Dispose (bool disposing)
74 // dispose unmanaged objects
76 // dispose managed objects
82 public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
84 if (inputCount != this.InputBlockSize)
85 throw new CryptographicException (Locale.GetText ("Invalid input length"));
87 byte[] lookup = Base64Constants.EncodeTable;
89 int b1 = inputBuffer [inputOffset];
90 int b2 = inputBuffer [inputOffset + 1];
91 int b3 = inputBuffer [inputOffset + 2];
93 outputBuffer [outputOffset] = lookup [b1 >> 2];
94 outputBuffer [outputOffset+1] = lookup [((b1 << 4) & 0x30) | (b2 >> 4)];
95 outputBuffer [outputOffset+2] = lookup [((b2 << 2) & 0x3c) | (b3 >> 6)];
96 outputBuffer [outputOffset+3] = lookup [b3 & 0x3f];
98 return this.OutputBlockSize;
101 // LAMESPEC: It's not clear from Beta2 docs what should be
102 // happening here if inputCount > InputBlockSize.
103 // It just "Converts the specified region of the specified
104 // byte array" and that's all.
105 // Beta2 implementation throws some strange (and undocumented)
106 // exception in such case. The exception is thrown by
107 // System.Convert and not the method itself.
108 // Anyhow, this implementation just encodes blocks of any size,
109 // like any usual Base64 encoder.
111 public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
113 int blockLen = this.InputBlockSize;
114 int outLen = this.OutputBlockSize;
115 int fullBlocks = inputCount / blockLen;
116 int tail = inputCount % blockLen;
118 byte[] res = new byte [(inputCount != 0)
119 ? ((inputCount + 2) / blockLen) * outLen
122 int outputOffset = 0;
124 for (int i = 0; i < fullBlocks; i++) {
126 TransformBlock (inputBuffer, inputOffset,
127 blockLen, res, outputOffset);
129 inputOffset += blockLen;
130 outputOffset += outLen;
133 byte[] lookup = Base64Constants.EncodeTable;
136 // When fewer than 24 input bits are available
137 // in an input group, zero bits are added
138 // (on the right) to form an integral number of
144 b1 = inputBuffer [inputOffset];
145 res [outputOffset] = lookup [b1 >> 2];
146 res [outputOffset+1] = lookup [(b1 << 4) & 0x30];
149 res [outputOffset+2] = (byte)'=';
150 res [outputOffset+3] = (byte)'=';
154 b1 = inputBuffer [inputOffset];
155 b2 = inputBuffer [inputOffset + 1];
156 res [outputOffset] = lookup [b1 >> 2];
157 res [outputOffset+1] = lookup [((b1 << 4) & 0x30) | (b2 >> 4)];
158 res [outputOffset+2] = lookup [(b2 << 2) & 0x3c];
161 res [outputOffset+3] = (byte)'=';