diff --git a/src/Microsoft.AspNetCore.WebUtilities/Base64UrlTextEncoder.cs b/src/Microsoft.AspNetCore.WebUtilities/Base64UrlTextEncoder.cs new file mode 100644 index 0000000000..0402429878 --- /dev/null +++ b/src/Microsoft.AspNetCore.WebUtilities/Base64UrlTextEncoder.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNetCore.WebUtilities +{ + public static class Base64UrlTextEncoder + { + /// + /// Encodes supplied data into Base64 and replaces any URL encodable characters into non-URL encodable + /// characters. + /// + /// Data to be encoded. + /// Base64 encoded string modified with non-URL encodable characters + public static string Encode(byte[] data) + { + return Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_'); + } + + /// + /// Decodes supplied string by replacing the non-URL encodable characters with URL encodable characters and + /// then decodes the Base64 string. + /// + /// The string to be decoded. + /// The decoded data. + public static byte[] Decode(string text) + { + return Convert.FromBase64String(Pad(text.Replace('-', '+').Replace('_', '/'))); + } + + private static string Pad(string text) + { + var padding = 3 - ((text.Length + 3) % 4); + if (padding == 0) + { + return text; + } + return text + new string('=', padding); + } + } +} diff --git a/test/Microsoft.AspNetCore.WebUtilities.Tests/Base64UrlTextEncoderTests.cs b/test/Microsoft.AspNetCore.WebUtilities.Tests/Base64UrlTextEncoderTests.cs new file mode 100644 index 0000000000..2034ea33d7 --- /dev/null +++ b/test/Microsoft.AspNetCore.WebUtilities.Tests/Base64UrlTextEncoderTests.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Xunit; + +namespace Microsoft.AspNetCore.WebUtilities +{ + public class Base64UrlTextEncoderTests + { + [Fact] + public void DataOfVariousLengthRoundTripCorrectly() + { + for (int length = 0; length != 256; ++length) + { + var data = new byte[length]; + for (int index = 0; index != length; ++index) + { + data[index] = (byte)(5 + length + (index * 23)); + } + string text = Base64UrlTextEncoder.Encode(data); + byte[] result = Base64UrlTextEncoder.Decode(text); + + for (int index = 0; index != length; ++index) + { + Assert.Equal(data[index], result[index]); + } + } + } + } +} \ No newline at end of file