web-dev-qa-db-ja.com

C#でBase64 URLセーフエンコーディングを実現する方法は?

C#でBase64 URLセーフエンコーディングを実現したい。 Javaには、URLに安全にエンコードされた文字列を提供する共通のCodecライブラリがあります。 C#を使用して同じことをどのように達成できますか?

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

上記のコードはBase64に変換しますが、==を埋め込みます。 URLセーフなエンコードを実現する方法はありますか?

80

一般的には、URLで使用するアルファベットを単純に交換するため、%エンコードは不要です。 65文字のうち、+/、および=の3つだけが問題です。最も一般的な置換は、-の代わりに+および_の代わりに/です。パディングに関して:ちょうどそれを削除します=);必要なパディングの量をinferできます。反対側:プロセスを逆にするだけです:

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

で:

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

そして逆に:

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

ただし、興味深い質問は次のとおりです。これは「一般的なコーデックライブラリ」が使用するのと同じアプローチですか? -これは非常に一般的なアプローチです。

150
Marc Gravell

名前空間Base64UrlEncoderのクラス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!");
61
Jerome

ここでのいくつかのパフォーマンス改善の回答に基づいて、非常に使いやすい NuGetへのURLセーフbase64実装 をソースコードで公開しました GitHubで利用可能 (MITライセンス)。

使い方は簡単です

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

ASP.NET Coreを使用している場合、別のオプションは Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode を使用することです。

ASP.NET Coreを使用していない場合、- WebEncoders sourceApache 2.0 License で利用できます。

7
Kevinoid

System.Web.HttpServerUtility.UrlTokenEncode(bytes)を使用してエンコードし、System.Web.HttpServerUtility.UrlTokenDecode(bytes)を使用してデコードします。

7
Karanvir Kang

UWPでMicrosoft暗号化エンジンを使用します。

uint length = 32;

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

return base64Str;
0
visc

Url-safe base64をデコードする別の方法は、Marcと同じ方法でエンコードされました。 4-length%4が動作した理由がわかりません(動作します)。

次のように、Originのビット長のみが6と8の公倍数です。base64は結果に「=」を追加しません。

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

結果のビット長が8で割り切れない場合は、逆に追加できます。

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