forked from PKISharp/ACMESharpCore
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from dlmelendez/rel/v2.x
Rel/v2.x
- Loading branch information
Showing
13 changed files
with
143 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,114 @@ | ||
using System; | ||
using System; | ||
using System.Text; | ||
|
||
namespace PKISharp.SimplePKI.Util | ||
{ | ||
// TODO:!!!!!! | ||
// This needs to be reconciled with the version in ACMESharp!!!! | ||
|
||
/// <summary> | ||
/// Collection of convenient crypto operations working | ||
/// with URL-safe Base64 encoding. | ||
/// </summary> | ||
internal class Base64Tool | ||
internal static class Base64Tool | ||
{ | ||
public static Base64Tool Instance = new Base64Tool(); | ||
|
||
|
||
/// <summary> | ||
/// URL-safe Base64 encoding as prescribed in RFC 7515 Appendix C. | ||
/// </summary> | ||
public string UrlEncode(string raw, Encoding encoding = null) | ||
public static ReadOnlySpan<char> UrlEncode(ReadOnlySpan<char> raw, Encoding encoding = null) | ||
{ | ||
if (encoding == null) | ||
encoding = Encoding.UTF8; | ||
return UrlEncode(encoding.GetBytes(raw)); | ||
encoding ??= Encoding.UTF8; | ||
Span<byte> rawBytes = stackalloc byte[encoding.GetMaxByteCount(raw.Length)]; | ||
bool getBytes = encoding.TryGetBytes(raw, rawBytes, out int bytesWritten); | ||
if (!getBytes) | ||
{ | ||
throw new InvalidOperationException("Failed to encode the input data to bytes."); | ||
} | ||
return UrlEncode(new Span<byte>([.. rawBytes.Slice(0, bytesWritten)])); | ||
} | ||
|
||
/// <summary> | ||
/// URL-safe Base64 encoding as prescribed in RFC 7515 Appendix C. | ||
/// </summary> | ||
public string UrlEncode(byte[] raw) | ||
public static ReadOnlySpan<char> UrlEncode(ReadOnlySpan<byte> raw) | ||
{ | ||
Span<char> enc = stackalloc char[GetMaxBase64Length(raw.Length)]; | ||
bool encoded = Convert.TryToBase64Chars(raw, enc, out int encodingCharCount, Base64FormattingOptions.None); | ||
if (!encoded) | ||
{ | ||
throw new InvalidOperationException("Failed to encode the input data to base64."); | ||
} | ||
enc.Replace('+', '-'); // 62nd char of encoding | ||
enc.Replace('/', '_'); // 63rd char of encoding | ||
//Find the first '=' and take the substring up to that point | ||
int indexOfFiller = enc.IndexOf<char>('='); | ||
if (indexOfFiller > 0) | ||
{ | ||
return new ReadOnlySpan<char>([.. enc.Slice(0, indexOfFiller)]); | ||
} | ||
return new ReadOnlySpan<char>([.. enc.Slice(0, encodingCharCount)]); | ||
} | ||
|
||
/// <summary> | ||
/// Calculate the maximum length of a URL-safe Base64 encoding from byte array length | ||
/// </summary> | ||
/// <param name="byteArrayLength"></param> | ||
/// <returns></returns> | ||
public static int GetMaxBase64Length(int byteArrayLength) | ||
{ | ||
string enc = Convert.ToBase64String(raw); // Regular base64 encoder | ||
enc = enc.Split('=')[0]; // Remove any trailing '='s | ||
enc = enc.Replace('+', '-'); // 62nd char of encoding | ||
enc = enc.Replace('/', '_'); // 63rd char of encoding | ||
return enc; | ||
return ((byteArrayLength + 2) / 3) * 4; | ||
} | ||
|
||
|
||
/// <summary> | ||
/// URL-safe Base64 decoding as prescribed in RFC 7515 Appendix C. | ||
/// </summary> | ||
public byte[] UrlDecode(string enc) | ||
public static ReadOnlySpan<byte> UrlDecode(ReadOnlySpan<char> enc) | ||
{ | ||
string raw = enc; | ||
raw = raw.Replace('-', '+'); // 62nd char of encoding | ||
raw = raw.Replace('_', '/'); // 63rd char of encoding | ||
switch (raw.Length % 4) // Pad with trailing '='s | ||
int encodedLength = enc.Length; | ||
//Create a Span<byte> to hold the encoded chars plus maximum padding | ||
Span<char> raw = stackalloc char[encodedLength + 2]; | ||
enc.CopyTo(raw); | ||
raw.Replace('-', '+'); // 62nd char of encoding | ||
raw.Replace('_', '/'); // 63rd char of encoding | ||
int padding = 0; | ||
|
||
// Pad with trailing '='s | ||
int mod = encodedLength % 4; | ||
if (mod != 0) | ||
{ | ||
if (mod == 2) | ||
{ | ||
// Two pad chars | ||
padding = 2; | ||
raw[encodedLength] = '='; | ||
raw[encodedLength + 1] = '='; | ||
} | ||
else if (mod == 3) | ||
{ | ||
// One pad char | ||
padding = 1; | ||
raw[encodedLength] = '='; | ||
} | ||
else | ||
{ | ||
throw new InvalidOperationException("Illegal base64url string!"); | ||
} | ||
} | ||
|
||
int totalEncodedLength = encodedLength + padding; | ||
int maxByteLength = (totalEncodedLength / 4) * 3; | ||
Span<byte> rawBytes = stackalloc byte[maxByteLength]; | ||
bool decoded = Convert.TryFromBase64Chars(raw.Slice(0, totalEncodedLength), rawBytes, out int bytesWritten); | ||
if (!decoded) | ||
{ | ||
case 0: break; // No pad chars in this case | ||
case 2: raw += "=="; break; // Two pad chars | ||
case 3: raw += "="; break; // One pad char | ||
default: | ||
throw new System.Exception("Illegal base64url string!"); | ||
throw new InvalidOperationException($"Failed to decode the input data from base64: {enc.ToString()}"); | ||
} | ||
return Convert.FromBase64String(raw); // Standard base64 decoder | ||
return new ReadOnlySpan<byte>([.. rawBytes.Slice(0, bytesWritten)]); // Standard base64 decoder | ||
} | ||
|
||
public string UrlDecodeToString(string enc, Encoding encoding = null) | ||
public static string UrlDecodeToString(ReadOnlySpan<char> enc, Encoding encoding = null) | ||
{ | ||
if (encoding == null) | ||
encoding = Encoding.UTF8; | ||
encoding ??= Encoding.UTF8; | ||
return encoding.GetString(UrlDecode(enc)); | ||
} | ||
}} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
test/PKISharp.SimplePKI.UnitTests/PKISharp.SimplePKI.UnitTests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.