wake-up-neo.net

Wie erreiche ich eine sichere Base64-URL-Verschlüsselung in C #?

Ich möchte eine sichere Base64-URL-Verschlüsselung in C # erzielen. In Java haben wir die gemeinsame Codec-Bibliothek, die mir eine URL-verschlüsselte Zeichenfolge gibt. Wie kann ich dasselbe mit C # erreichen?

byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes("StringToEncode");
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

Der obige Code konvertiert es in Base64, füllt jedoch ==. Gibt es eine Möglichkeit, eine URL-sichere Kodierung zu erreichen?

71

Es ist üblich, einfach Alphabet austauschen für die Verwendung in URLs zu verwenden, so dass keine% -Encodierung erforderlich ist. Nur 3 der 65 Zeichen sind problematisch - +, / und =. Die häufigsten Ersetzungen sind - anstelle von + und _ anstelle von /. Bezüglich der Auffüllung: einfach entfernen (der =); Sie können ableiten die benötigte Auffüllmenge. Am anderen Ende: einfach den Vorgang umkehren:

string returnValue = System.Convert.ToBase64String(toEncodeAsBytes)
        .TrimEnd(padding).Replace('+', '-').Replace('/', '_');

mit:

static readonly char[] padding = { '=' };

und umzukehren:

string incoming = returnValue
    .Replace('_', '/').Replace('-', '+');
switch(returnValue.Length % 4) {
    case 2: incoming += "=="; break;
    case 3: incoming += "="; break;
}
byte[] bytes = Convert.FromBase64String(incoming);
string originalText = Encoding.ASCII.GetString(bytes);

Die interessante Frage ist jedoch: ist dies derselbe Ansatz, den die "Common Codec Library" verwendet? Es wäre sicherlich ein vernünftiger erster Test - dies ist ein ziemlich allgemeiner Ansatz.

132
Marc Gravell

Sie können die Klasse Base64UrlEncoder aus dem Namensraum Microsoft.IdentityModel.Tokens verwenden.

const string StringToEncode = "He=llo+Wo/rld";

var encodedStr = Base64UrlEncoder.Encode(StringToEncode);
var decodedStr = Base64UrlEncoder.Decode(encodedStr);

if (decodedStr == StringToEncode)
    Console.WriteLine("It works!");
else
    Console.WriteLine("Dangit!");
49
Jerome

Verwenden Sie zum Kodieren System.Web.HttpServerUtility.UrlTokenEncode (Bytes) und zum Dekodieren System.Web.HttpServerUtility.UrlTokenDecode (Byte).

6
Karanvir Kang

Basierend auf den Antworten mit einigen Leistungsverbesserungen haben wir eine sehr benutzerfreundliche url-safe base64-Implementierung für NuGet mit dem Quellcode veröffentlicht, die auf GitHub (MIT-lizenziert) verfügbar ist.

Die Verwendung ist so einfach wie

var bytes = Encoding.UTF8.GetBytes("Foo");
var encoded = UrlBase64.Encode(bytes);
var decoded = UrlBase64.Decode(encoded);
6

Wenn Sie ASP.NET Core verwenden, können Sie auch Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode verwenden.

Wenn Sie ASP.NET Core nicht verwenden, ist die WebEncoders-Quelle unter der Apache 2.0-Lizenz verfügbar.

3
Kevinoid

Verwenden der Microsoft Cryptographic Engine in UWP.

uint length = 32;

IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
string base64Str = CryptographicBuffer.EncodeToBase64String(buffer)
                   // ensure url safe
                   .TrimEnd('=').Replace('+', '-').Replace('/', '_');

return base64Str;
0
visc

Hier ist eine weitere Methode zum Decodieren einer url-sicheren Base64, die auf dieselbe Weise wie Marc codiert wurde. Ich verstehe einfach nicht, warum 4-length%4 funktioniert hat (es funktioniert).

Wie folgt, ist nur die Bitlänge des Ursprungs ein gemeinsames Vielfaches von 6 und 8, Base64 fügt kein "=" an das Ergebnis an.

1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8 
1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6
                "=="            "="

So können wir es umgekehrt machen, wenn die Bitlänge des Ergebnisses nicht durch 8 teilbar ist, wurde es angehängt:

base64String = base64String.Replace("-", "+").Replace("_", "/");
var base64 = Encoding.ASCII.GetBytes(base64String);
var padding = base64.Length * 3 % 4;//(base64.Length*6 % 8)/2
if (padding != 0)
{
    base64String = base64String.PadRight(base64String.Length + padding, '=');
}
return Convert.FromBase64String(base64String);
0
joyjy