Mã để giải mã / mã hóa URL base64 đã sửa đổi


113

Tôi muốn mã hóa dữ liệu base64 để đưa nó vào một URL và sau đó giải mã nó trong HttpHandler của tôi.

Tôi nhận thấy rằng Mã hóa Base64 cho phép ký tự '/' sẽ làm xáo trộn kết hợp UriTemplate của tôi. Sau đó, tôi thấy rằng có một khái niệm về "Base64 được sửa đổi cho URL" từ wikipedia:

Có một biến thể Base64 được sửa đổi cho URL tồn tại, nơi không sử dụng padding '=' và các ký tự '+' và '/' của Base64 chuẩn được thay thế tương ứng bằng '-' và '_', để sử dụng bộ mã hóa / giải mã URL không còn cần thiết và không ảnh hưởng đến độ dài của giá trị được mã hóa, giữ nguyên dạng được mã hóa tương tự để sử dụng trong cơ sở dữ liệu quan hệ, biểu mẫu web và mã định danh đối tượng nói chung.

Sử dụng .NET, tôi muốn sửa đổi mã hiện tại của mình từ thực hiện mã hóa và giải mã base64 cơ bản sang sử dụng phương pháp "base64 được sửa đổi cho URL". Có ai đã làm điều này?

Để giải mã, tôi biết nó bắt đầu với một cái gì đó như:

string base64EncodedText = base64UrlEncodedText.Replace('-', '+').Replace('_', '/');

// Append '=' char(s) if necessary - how best to do this?

// My normal base64 decoding now uses encodedText

Tuy nhiên, tôi có thể cần thêm một hoặc hai ký tự '=' vào cuối, trông phức tạp hơn một chút.

Logic mã hóa của tôi nên đơn giản hơn một chút:

// Perform normal base64 encoding
byte[] encodedBytes = Encoding.UTF8.GetBytes(unencodedText);
string base64EncodedText = Convert.ToBase64String(encodedBytes);

// Apply URL variant
string base64UrlEncodedText = base64EncodedText.Replace("=", String.Empty).Replace('+', '-').Replace('/', '_');

Tôi đã xem Hướng dẫn Base64 cho mục nhập URL StackOverflow, nhưng điều đó có độ dài đã biết và do đó chúng có thể mã hóa số lượng dấu bằng cần thiết ở cuối.


@Kirk: Điều chỉnh câu trả lời của tôi bằng toán đã kiểm tra.
AnthonyWJones

Câu trả lời:


69

Điều này nên viết nó ra một cách chính xác: -

 base64 = base64.PadRight(base64.Length + (4 - base64.Length % 4) % 4, '=');

11
Bah, bạn đã đánh bại tôi. Tôi sẽ chỉ cần xóa bài của tôi vì nó trông gần giống như tôi sao chép bạn :)
AaronLS

3
Điều này sẽ không thêm tối đa ba ký tự '='? Có vẻ như sẽ chỉ có 0, 1 hoặc 2 trong số này.
Kirk Liemohn

1
@Kirk: Nếu nó thêm 3 ký tự thì chuỗi base64 đã bị hỏng. Tôi đoán nó sẽ là một ý tưởng tốt để xác nhận chuỗi, nó sẽ chỉ chứa các ký tự mong đợi và% 4 Chiều dài = 3.!
AnthonyWJones

Hừ! Khi thử điều này, nó không phải là thủ thuật. Vẫn đang tìm kiếm câu trả lời. Số lượng các dấu bằng không được di chuyển đúng cách.
Kirk Liemohn

2
@AnthonyWJones 'nó chỉ nên chứa các ký tự mong đợi và Độ dài% 4! = 1 ', phải không?
blueling

173

Đồng thời kiểm tra lớp HttpServerUtility với các phương thức UrlTokenEncode và UrlTokenDecode đang xử lý mã hóa và giải mã Base64 an toàn cho URL.

Lưu ý 1: Kết quả không phải là một chuỗi Base64 hợp lệ. Một số ký tự không an toàn cho URL được thay thế.

Lưu ý 2: Kết quả khác với thuật toán base64url trong RFC4648.

///<summary>
/// Base 64 Encoding with URL and Filename Safe Alphabet using UTF-8 character set.
///</summary>
///<param name="str">The origianl string</param>
///<returns>The Base64 encoded string</returns>
public static string Base64ForUrlEncode(string str)
{
    byte[] encbuff = Encoding.UTF8.GetBytes(str);
    return HttpServerUtility.UrlTokenEncode(encbuff);
}
///<summary>
/// Decode Base64 encoded string with URL and Filename Safe Alphabet using UTF-8.
///</summary>
///<param name="str">Base64 code</param>
///<returns>The decoded string.</returns>
public static string Base64ForUrlDecode(string str)
{
    byte[] decbuff = HttpServerUtility.UrlTokenDecode(str);
    return Encoding.UTF8.GetString(decbuff);
}

Cảm ơn vì tiền hỗ trợ. Tôi sẽ thử điều đó vào lần sau!
Kirk Liemohn

12
Mẹo của bạn là kết thúc tuyệt vời cho một cuộc tìm kiếm nhiều giờ và búi tóc cho câu trả lời. cảm ơn
Praesagus

Điều này sẽ không sử dụng mã hóa% cho mọi / + và =? Đây không phải là hiệu quả như câu trả lời khác
JoelFan

Không, nó thay thế các dấu bằng được sử dụng để đệm cuối cùng bằng một số và thay thế dấu cộng và dấu gạch ngang bằng dấu trừ và dấu gạch dưới.
Fredrik Haglund

15
Lưu ý rằng UrlTokenEncodekhông hoàn toàn là base64url , vì nó thay thế phần đệm '=' bằng '0', '1' hoặc '2' tùy thuộc vào số lượng dấu bằng mà nó thay thế.
ladenedge

28

Không đủ điểm để nhận xét, nhưng trong trường hợp có ích, đoạn mã mà Sushil tìm thấy trong liên kết được cung cấp (bản nháp ietf của Chữ ký Web JSON) sẽ hoạt động khi mã hóa Base 64 dưới dạng tham số trong URL.

Đoạn mã được sao chép dưới đây cho những người lười biếng:

    static string Base64UrlEncode(byte[] arg)
    {
        string s = Convert.ToBase64String(arg); // Regular base64 encoder
        s = s.Split('=')[0]; // Remove any trailing '='s
        s = s.Replace('+', '-'); // 62nd char of encoding
        s = s.Replace('/', '_'); // 63rd char of encoding
        return s;
    }

    static byte[] Base64UrlDecode(string arg)
    {
        string s = arg;
        s = s.Replace('-', '+'); // 62nd char of encoding
        s = s.Replace('_', '/'); // 63rd char of encoding
        switch (s.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 2: s += "=="; break; // Two pad chars
            case 3: s += "="; break; // One pad char
            default: throw new System.Exception(
              "Illegal base64url string!");
        }
        return Convert.FromBase64String(s); // Standard base64 decoder
    }

đây là tương thích với Xamarin cho không sử dụng System.Web
Reza Mortazavi

Chính xác những gì tôi đang tìm kiếm! Lựa chọn thực sự tốt cho Xamarin mà không cần phải kéo vào thư viện.
Sleeping_Giant

19

Tôi nhấn vào đây trong khi tìm mã để thực hiện mã hóa / giải mã cho mã hóa base64url hơi khác so với base64 như đã giải thích trong câu hỏi.

Đã tìm thấy đoạn mã c # trong tài liệu này. Bản nháp ietf Chữ ký Web JSON


2
Đây là giải pháp duy nhất phù hợp với tôi khi phân tích cú pháp một tin nhắn trong API GMail v1 (
Message.Raw

5

So với câu trả lời được chấp nhận, đây là cách bạn sẽ giải mã cơ bản một url được mã hóa base64, sử dụng C #:

Giải mã:

string codedValue = "base64encodedUrlHere";

string decoded;
byte[] buffer =  Convert.FromBase64String(codedValue);
decoded = Encoding.UTF8.GetString(buffer);

có lẽ nếu bạn cung cấp thêm chi tiết và so sánh với các câu trả lời được chấp nhận, bạn có thể nhận được một phiếu bầu tán thành - nhờ
Mauricio Gracia Gutierrez
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.