C # ile Base64 URL güvenli kodlaması nasıl elde edilir?


107

C # ile Base64 URL güvenli kodlamasına ulaşmak istiyorum. Java'da, Codecbana URL güvenli kodlanmış dizesi veren ortak kitaplığımız var. C # kullanarak aynısını nasıl başarabilirim?

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

Yukarıdaki kod, onu Base64'e dönüştürür, ancak değiştirir ==. Güvenli URL kodlamasına ulaşmanın bir yolu var mı?


1
Kullanmak sadece Can not Url.Encodeşerit üzerinde BASE64?

Hangi ad alanında Url sınıfı c # 'da bulunur?
Vishvesh Phadnis

Bir göz atın: msdn.microsoft.com/en-us/library/… Derlemeye başvurmanız gerekir System.Web.

=% 3D'ye dönüştürülüyor. Bunu istemiyorum
Vishvesh Phadnis

3
Peki ne demek istiyorsun url safe? %3Durl güvenli.

Yanıtlar:


184

URL'lerde kullanmak için alfabeyi değiştirmek yaygındır , böylece% kodlaması gerekmez; sadece 3 65 karakter sorunlu - +, /ve =. en yaygın değiştirmeler -yerine +ve _yerine gelir /. Dolguya gelince: sadece çıkarın (the =); gerekli dolgu miktarını tahmin edebilirsiniz . Diğer tarafta: sadece süreci tersine çevirin:

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

ile:

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

ve tersine çevirmek için:

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

Bununla birlikte, ilginç soru şudur: Bu, "ortak kodek kitaplığının" kullandığı yaklaşımın aynısı mı? Test etmek kesinlikle makul bir ilk şey olacaktır - bu oldukça yaygın bir yaklaşımdır.


1
Ortak Codec'te, url güvenli mod için [0-9a-zA-Z_-] Karakterini kullanıyorlar.
Vishvesh Phadnis

bu aynı zamanda URL uygulamaları altında Base64 için wiki sayfasında da belirtilmiştir. en.wikipedia.org/wiki/Base64
wonster

2
Ayrıca , tüm zor işi sizin için yapan ' stackoverflow.com/questions/1886686/… ' işlevine de sahipsiniz.
toy4fun

1
Neden ihtiyacımız yok: durum 1: gelen + = "==="; kırmak; ?
alex da franca

5
@alexdafranca asla 1'lik bir uzunluk moduna sahip olmayacağı için. 3x8 bit, 4x6 bit olur (ve her 6 bit, seçilen alfabedeki 64 karakterden biridir), 0x8 bit, dolgu olmadan 0x6 bit olarak kodlanır, 1x8 bit olarak kodlanır ile 2x6 bit ==dolgu, 2x8 ile 3x6 olarak kodlanan =dolgu, 3x8 padding'siz 4x6 olarak kodlanır ve tekrar, böylece daha sonra hizalanır. Hiçbir şey 1x6 bit olarak kodlanmaz, bu nedenle hiçbir zaman ===doldurmaya ihtiyacınız olmaz .
George Helyar

83

Base64UrlEncoderAd alanından sınıfı kullanabilirsiniz 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!");

1
Bu, kabul edilen cevaptan çok daha temiz. Olumsuz tarafı var mı?
taktak004

19
Sadece bir not: Microsoft.IdentityModel.Tokens, indirilmesi gereken bir NuGet paketidir.
Uber Schnoz

İsminden bunun çapraz platform olmadığını varsayıyorum. Durum bu mu?
Brandon S.


8

Bazı performans iyileştirmeleriyle birlikte buradaki yanıtlara dayanarak , GitHub'da bulunan kaynak koduyla (MIT lisanslı) NuGet'e kullanımı çok kolay bir url güvenli base64 uygulaması yayınladık .

Kullanımı kadar kolaydır

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

Şaşırtıcı teşekkürler. Eğer tercih niçin ilgi Out "string".Replaceiçin encodeyöntemiyle, ama için manuel cümledeki ile bir döngü decode?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

@ ᴍᴀᴛᴛʙᴀᴋᴇʀ Onu tekrar gözden geçirmem ve bazı kriterler çalıştırmam gerekiyor, ancak bunun nedeni ikincisini eklememiz ve böylece değişmez bir dizge yerine büyütülebilir bir karakter listesiyle temsil edilmesidir.
Mahmud El-Kudsi

Bunun yerine dönüş türüne sahip başka bir sınıf = string: github.com/vndevpro/architecture-common/blob/master/…
hazjack

8

URL güvenli base64 benzeri bir kodlama elde etmek, ancak RFC4648'e göre "base64url" alamamak için, System.Web.HttpServerUtility.UrlTokenEncode(bytes)kodlamak ve System.Web.HttpServerUtility.UrlTokenDecode(bytes)kodunu çözmek için kullanın.


6
Bu, RFC4648'e göre standartlara uygun URL güvenli Base64 kodlaması sağlamaz. Ayrıca bu Soru-Cevap bölümüne bakın . Dikkatle kullanın.
Artjom B.

1

En basit çözüm: (dolgu olmadan)

private static string Base64UrlEncode(string input) {
    var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
    // Special "url-safe" base64 encode.
    return Convert.ToBase64String(inputBytes)
      .Replace('+', '-') // replace URL unsafe characters with safe ones
      .Replace('/', '_') // replace URL unsafe characters with safe ones
      .Replace("=", ""); // no padding
  }

Kredi: Tholle


0

İşte url güvenli bir base64 kodunu çözmek için başka bir yöntem, Marc ile aynı şekilde kodlanmıştır. Sadece neden 4-length%4çalıştığını anlamıyorum (işe yarıyor).

Aşağıdaki gibi, yalnızca orijinin bit uzunluğu 6 ve 8'in ortak katıdır, base64 sonuca "=" eklemeyin.

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

Yani bunu tersine yapabiliriz, eğer sonucun bit uzunluğu 8'e bölünemezse, sonuç eklenir:

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

UWP'de Microsoft şifreleme motorunu kullanma.

uint length = 32;

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

return base64Str;

0

Karanvir Kang'ın cevabı iyi ve ona oy verdim. Bununla birlikte, dizenin sonunda tek bir karakter bırakır (kaldırılan dolgu karakterlerinin sayısını gösterir). İşte benim çözümüm.

var bytesToEncode = System.Text.Encoding.UTF8.GetBytes("StringToEncode"); 
var bytesEncodedPadded = HttpServerUtility.UrlTokenEncode(bytesToEncode);
var objectIdBase64 = bytesEncodedPadded.Substring(0, bytesEncodedPadded.Length - 1);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.