<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" />

Base64Encoder

public class Base64Encoder : IEncoder
using System; using System.IO; namespace Org.BouncyCastle.Utilities.Encoders { public class Base64Encoder : IEncoder { protected readonly byte[] encodingTable = new byte[64] { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 }; protected byte padding = 61; protected readonly byte[] decodingTable = new byte[128]; protected void InitialiseDecodingTable() { Arrays.Fill(decodingTable, byte.MaxValue); for (int i = 0; i < encodingTable.Length; i++) { decodingTable[encodingTable[i]] = (byte)i; } } public Base64Encoder() { InitialiseDecodingTable(); } public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff) { return Encode(inBuf.AsSpan(inOff, inLen), outBuf.AsSpan(outOff)); } public int Encode(ReadOnlySpan<byte> input, Span<byte> output) { int num = 0; int num2 = input.Length - 2; int num3 = 0; while (num < num2) { uint num5 = input[num++]; uint num7 = input[num++]; uint num9 = input[num++]; output[num3++] = encodingTable[(num5 >> 2) & 63]; output[num3++] = encodingTable[((num5 << 4) | (num7 >> 4)) & 63]; output[num3++] = encodingTable[((num7 << 2) | (num9 >> 6)) & 63]; output[num3++] = encodingTable[num9 & 63]; } switch (input.Length - num) { case 1: { uint num23 = input[num++]; output[num3++] = encodingTable[(num23 >> 2) & 63]; output[num3++] = encodingTable[(num23 << 4) & 63]; output[num3++] = padding; output[num3++] = padding; break; } case 2: { uint num15 = input[num++]; uint num17 = input[num++]; output[num3++] = encodingTable[(num15 >> 2) & 63]; output[num3++] = encodingTable[((num15 << 4) | (num17 >> 4)) & 63]; output[num3++] = encodingTable[(num17 << 2) & 63]; output[num3++] = padding; break; } } return num3; } public int Encode(byte[] buf, int off, int len, Stream outStream) { return Encode(buf.AsSpan(off, len), outStream); } public unsafe int Encode(ReadOnlySpan<byte> data, Stream outStream) { Span<byte> output = new Span<byte>(stackalloc byte[72], 72); int result = (data.Length + 2) / 3 * 4; while (!data.IsEmpty) { int num = System.Math.Min(54, data.Length); int length = Encode(data.Slice(0, num), output); outStream.Write(output.Slice(0, length)); int num2 = num; data = data.Slice(num2, data.Length - num2); } return result; } private bool Ignore(char c) { if (c != '\n' && c != '\r' && c != '\t') return c == ' '; return true; } public int Decode(byte[] data, int off, int length, Stream outStream) { return Decode(data.AsSpan(off, length), outStream); } public unsafe int Decode(ReadOnlySpan<byte> data, Stream outStream) { Span<byte> span = new Span<byte>(stackalloc byte[54], 54); int num = 0; int num2 = 0; int num3 = data.Length; while (num3 > 0 && Ignore((char)data[num3 - 1])) { num3--; } int num4 = num3 - 4; int num5; for (num5 = NextI(data, 0, num4); num5 < num4; num5 = NextI(data, num5, num4)) { byte b = decodingTable[data[num5++]]; num5 = NextI(data, num5, num4); byte b2 = decodingTable[data[num5++]]; num5 = NextI(data, num5, num4); byte b3 = decodingTable[data[num5++]]; num5 = NextI(data, num5, num4); byte b4 = decodingTable[data[num5++]]; if ((b | b2 | b3 | b4) >= 128) throw new IOException("invalid characters encountered in base64 data"); span[num++] = (byte)((b << 2) | (b2 >> 4)); span[num++] = (byte)((b2 << 4) | (b3 >> 2)); span[num++] = (byte)((b3 << 6) | b4); if (num == span.Length) { outStream.Write(span); num = 0; } num2 += 3; } if (num > 0) outStream.Write(span.Slice(0, num)); int num13 = NextI(data, num5, num3); int num14 = NextI(data, num13 + 1, num3); int num15 = NextI(data, num14 + 1, num3); int index = NextI(data, num15 + 1, num3); return num2 + DecodeLastBlock(outStream, (char)data[num13], (char)data[num14], (char)data[num15], (char)data[index]); } private int NextI(ReadOnlySpan<byte> data, int i, int finish) { while (i < finish && Ignore((char)data[i])) { i++; } return i; } public unsafe int DecodeString(string data, Stream outStream) { int num = 0; int num2 = data.Length; while (num2 > 0 && Ignore(data[num2 - 1])) { num2--; } int num3 = num2 - 4; int num4 = NextI(data, 0, num3); Span<byte> span = new Span<byte>(stackalloc byte[3], 3); while (num4 < num3) { byte b = decodingTable[data[num4++]]; num4 = NextI(data, num4, num3); byte b2 = decodingTable[data[num4++]]; num4 = NextI(data, num4, num3); byte b3 = decodingTable[data[num4++]]; num4 = NextI(data, num4, num3); byte b4 = decodingTable[data[num4++]]; if ((b | b2 | b3 | b4) >= 128) throw new IOException("invalid characters encountered in base64 data"); span[0] = (byte)((b << 2) | (b2 >> 4)); span[1] = (byte)((b2 << 4) | (b3 >> 2)); span[2] = (byte)((b3 << 6) | b4); outStream.Write(span); num += 3; num4 = NextI(data, num4, num3); } return num + DecodeLastBlock(outStream, data[num2 - 4], data[num2 - 3], data[num2 - 2], data[num2 - 1]); } private unsafe int DecodeLastBlock(Stream outStream, char c1, char c2, char c3, char c4) { if (c3 == padding) { if (c4 != padding) throw new IOException("invalid characters encountered at end of base64 data"); byte b = decodingTable[c1]; byte b2 = decodingTable[c2]; if ((b | b2) >= 128) throw new IOException("invalid characters encountered at end of base64 data"); outStream.WriteByte((byte)((b << 2) | (b2 >> 4))); return 1; } if (c4 == padding) { byte b3 = decodingTable[c1]; byte b4 = decodingTable[c2]; byte b5 = decodingTable[c3]; if ((b3 | b4 | b5) >= 128) throw new IOException("invalid characters encountered at end of base64 data"); byte* intPtr = stackalloc byte[2]; *intPtr = (byte)((b3 << 2) | (b4 >> 4)); intPtr[1] = (byte)((b4 << 4) | (b5 >> 2)); Span<byte> span = new Span<byte>(intPtr, 2); outStream.Write(span); return 2; } byte b6 = decodingTable[c1]; byte b7 = decodingTable[c2]; byte b8 = decodingTable[c3]; byte b9 = decodingTable[c4]; if ((b6 | b7 | b8 | b9) >= 128) throw new IOException("invalid characters encountered at end of base64 data"); byte* intPtr2 = stackalloc byte[3]; *intPtr2 = (byte)((b6 << 2) | (b7 >> 4)); intPtr2[1] = (byte)((b7 << 4) | (b8 >> 2)); intPtr2[2] = (byte)((b8 << 6) | b9); Span<byte> span2 = new Span<byte>(intPtr2, 3); outStream.Write(span2); return 3; } private int NextI(string data, int i, int finish) { while (i < finish && Ignore(data[i])) { i++; } return i; } } }