web-dev-qa-db-fra.com

Comment réaliser un encodage sécurisé en Base # URL en C #?

Je souhaite obtenir le codage sécurisé en base CURL des URL Base64. En Java, nous avons la bibliothèque Codec commune qui me donne une chaîne encodée sécurisée par une URL. Comment puis-je obtenir la même chose avec C #?

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

Le code ci-dessus le convertit en Base64, mais il compresse ==. Existe-t-il un moyen d'obtenir un codage sécurisé des URL?

71
Vishvesh Phadnis

Il est commun de simplement échanger l'alphabet pour une utilisation dans les URL, de sorte qu'aucun codage% n'est nécessaire; seuls 3 des 65 caractères posent problème - +, / et =. les remplacements les plus courants sont - à la place de + et _ à la place de /. En ce qui concerne le remplissage: il suffit de le supprimer (le =); vous pouvez déduire la quantité de rembourrage nécessaire. À l'autre bout: inversez le processus:

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

avec:

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

et inverser:

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);

La question intéressante, cependant, est: est-ce la même approche que celle utilisée par la "bibliothèque de codecs commune"? Ce serait certainement une première chose raisonnable de tester - c'est une approche assez commune.

132
Marc Gravell

Vous pouvez utiliser la classe Base64UrlEncoder de l'espace de noms Microsoft.IdentityModel.Tokens.

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

Utilisez System.Web.HttpServerUtility.UrlTokenEncode (octets) pour coder et System.Web.HttpServerUtility.UrlTokenDecode (octets) pour décoder.

6
Karanvir Kang

Sur la base des réponses apportées, avec quelques améliorations de performances, nous avons publié une implémentation très facile à utiliser url-safe base64 dans NuGet avec le code source disponible sur GitHub (sous licence MIT).

L'utilisation est aussi simple que

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

Si vous utilisez ASP.NET Core, vous pouvez également utiliser Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode .

Si vous n'utilisez pas ASP.NET Core, la source WebEncoders est disponible sous Apache 2.0 License .

3
Kevinoid

Utilisation du moteur de cryptographie Microsoft dans UWP.

uint length = 32;

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

return base64Str;
0
visc

Voici une autre méthode pour décoder une base64 sécurisée pour l’URL qui a été encodée de la même manière avec Marc. Je ne comprends tout simplement pas pourquoi 4-length%4 a fonctionné (cela fonctionne).

Comme suit, seules les longueurs de bits de l’Origine sont communes à 6 et 8, base64 n’ajoutant pas "=" au résultat.

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
                "=="            "="

Nous pouvons donc le faire à l'inverse, si la longueur en bits du résultat ne peut pas être divisible par 8, elle a été ajoutée:

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