จะบรรลุการเข้ารหัสที่ปลอดภัยของ URL Base64 ใน C # ได้อย่างไร


114

ฉันต้องการบรรลุการเข้ารหัสที่ปลอดภัยของ URL Base64 ใน C # ใน Java เรามีCodecไลบรารีทั่วไปที่ให้สตริงเข้ารหัสที่ปลอดภัยสำหรับ URL ฉันจะบรรลุสิ่งเดียวกันโดยใช้ C # ได้อย่างไร

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

รหัสข้างต้นแปลงไป Base64 ==แต่มันแผ่น มีวิธีการเข้ารหัส URL ที่ปลอดภัยหรือไม่?


1
คุณไม่สามารถใช้Url.Encodeกับสตริงได้BASE64หรือไม่?

เนมสเปซ URL คลาสใดที่มีอยู่ใน c #
Vishvesh Phadnis

ลองดู: msdn.microsoft.com/en-us/library/…คุณต้องอ้างอิงSystem.Webแอสเซมบลี

มันกำลังแปลง = เป็น% 3D ฉันไม่ต้องการสิ่งนั้น
Vishvesh Phadnis

3
แล้วคุณหมายถึงurl safeอะไร? %3Durl ปลอดภัย

คำตอบ:


193

เป็นเรื่องปกติที่จะเพียงแค่สลับตัวอักษรเพื่อใช้ใน URL ดังนั้นจึงไม่จำเป็นต้องมีการเข้ารหัส% เพียง 3 ของ 65 ตัวอักษรมีปัญหา - +, และ/ =ทดแทนที่พบมากที่สุด-ในสถานที่+และในสถานที่ของ_ /สำหรับช่องว่างภายใน: เพียงแค่เอาออก (the =); คุณสามารถสรุปจำนวนช่องว่างที่ต้องการได้ ในอีกด้านหนึ่ง: เพียงย้อนกลับกระบวนการ:

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

อย่างไรก็ตามคำถามที่น่าสนใจคือนี่เป็นแนวทางเดียวกับที่ "ไลบรารีตัวแปลงสัญญาณทั่วไป" ใช้หรือไม่ แน่นอนว่าเป็นสิ่งแรกที่สมเหตุสมผลในการทดสอบ - นี่เป็นแนวทางที่พบได้บ่อย


1
ใน Codec ทั่วไปพวกเขากำลังใช้อักขระ [0-9a-zA-Z_-] สำหรับ url เซฟโหมด
Vishvesh Phadnis

สิ่งนี้ยังกล่าวถึงในหน้าวิกิสำหรับ Base64 ภายใต้แอปพลิเคชัน URL en.wikipedia.org/wiki/Base64
wonster

2
คุณยังมีฟังก์ชั่นนี้ ' stackoverflow.com/questions/1886686/… ' ซึ่งทำงานหนักทั้งหมดให้กับคุณ
toy4fun

1
ทำไมเราไม่ต้องการ: กรณีที่ 1: ขาเข้า + = "==="; หยุดพัก; เหรอ?
alex da franca

6
@alexdafranca เพราะจะไม่มี mod ที่มีความยาว 4 เท่ากับ 1 3x8 บิตกลายเป็น 4x6 บิต (และแต่ละ 6 บิตเป็นอักขระ 64 ตัวในตัวอักษรที่เลือก) 0x8 บิตถูกเข้ารหัสเป็น 0x6 บิตโดยไม่มีช่องว่างภายใน 1x8 บิตถูกเข้ารหัสเป็น 2x6 บิตที่มี==ช่องว่างภายใน, 2x8 ถูกเข้ารหัสเป็น 3x6 พร้อม=ช่องว่างภายใน, 3x8 ถูกเข้ารหัสเป็น 4x6 โดยไม่มีช่องว่างภายในจากนั้นจะถูกจัดแนวเพื่อให้ทำซ้ำ ไม่มีสิ่งใดที่เคยเข้ารหัสเป็น 1x6 บิตดังนั้นคุณไม่จำเป็นต้องมี===ช่องว่างภายใน
George Helyar

89

คุณสามารถใช้ระดับBase64UrlEncoderจาก Microsoft.IdentityModel.Tokensnamespace

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
สิ่งนี้สะอาดกว่าคำตอบที่ยอมรับมาก ข้อเสียใด ๆ ?
taktak004

21
หมายเหตุ: Microsoft.IdentityModel.Tokens เป็นแพ็คเกจ NuGet ที่ต้องดาวน์โหลด
Uber Schnoz

ฉันตั้งสมมติฐานว่านี่ไม่ใช่ข้ามแพลตฟอร์ม เป็นอย่างนั้นหรือ?
Brandon S.


8

จากคำตอบที่นี่พร้อมการปรับปรุงประสิทธิภาพบางอย่างเราได้เผยแพร่การใช้งานurl-safe base64 ที่ใช้งานง่ายกับNuGetด้วยซอร์สโค้ดที่มีอยู่ใน GitHub (MIT ได้รับอนุญาต)

การใช้งานนั้นง่ายพอ ๆ

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

ขอบคุณมาก ออกจากดอกเบี้ยทำไมคุณเลือก"string".Replaceสำหรับencodeวิธีการ แต่ห่วงกับแทนที่ด้วยตนเองสำหรับการเป็นdecode?
ᴍᴀᴛᴛʙᴀᴋᴇʀ

@ ᴍᴀᴛᴛʙᴀᴋᴇʀฉันต้องกลับมาดูและเรียกใช้การวัดประสิทธิภาพบางอย่าง แต่เป็นเพราะเราเพิ่มเข้าไปในส่วนหลังดังนั้นจึงแสดงด้วยรายการอักขระที่เติบโตได้แทนที่จะเป็นสตริงที่ไม่เปลี่ยนรูป
Mahmoud Al-Qudsi

คลาสอื่นที่มี return type = string แทน: github.com/vndevpro/architecture-common/blob/master/…
hazjack

8

หากต้องการรับการเข้ารหัสแบบ base64 ที่ปลอดภัยต่อ URL แต่ไม่ใช่ "base64url" ตาม RFC4648 ให้ใช้System.Web.HttpServerUtility.UrlTokenEncode(bytes)ในการเข้ารหัสและ System.Web.HttpServerUtility.UrlTokenDecode(bytes)ถอดรหัส


7
สิ่งนี้ไม่ได้ให้มาตรฐานที่สอดคล้องกับการเข้ารหัส Base64 ที่ปลอดภัยต่อ URL ตาม RFC4648 ดูถาม & ตอบนี้ด้วย ใช้ด้วยความระมัดระวัง
Artjom B.

1

วิธีแก้ไขที่ง่ายที่สุด: (โดยไม่มีช่องว่างภายใน)

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
  }

เครดิตไปที่: Tholle


0

นี่เป็นอีกวิธีหนึ่งในการถอดรหัส url-safe base64 ที่เข้ารหัสด้วยวิธีเดียวกันกับ Marc ฉันไม่เข้าใจว่าทำไมถึง4-length%4ได้ผล (เป็นเช่นนั้น)

ดังต่อไปนี้เฉพาะความยาวบิตของจุดเริ่มต้นเท่านั้นที่เป็นตัวคูณทั่วไปของ 6 และ 8 ฐาน 64 ไม่ผนวก "=" เข้ากับผลลัพธ์

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

การใช้เอ็นจิ้นการเข้ารหัสของ Microsoft ใน UWP

uint length = 32;

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

return base64Str;

0

คำตอบของ Karanvir Kang เป็นคำตอบที่ดีและฉันโหวตให้ อย่างไรก็ตามจะทิ้งอักขระแปลก ๆ ไว้ที่ท้ายสตริง (ระบุจำนวนอักขระช่องว่างภายในที่ลบออก) นี่คือทางออกของฉัน

var bytesToEncode = System.Text.Encoding.UTF8.GetBytes("StringToEncode"); 
var bytesEncodedPadded = HttpServerUtility.UrlTokenEncode(bytesToEncode);
var objectIdBase64 = bytesEncodedPadded.Substring(0, bytesEncodedPadded.Length - 1);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.