C #에서 Base64 URL 안전 인코딩을 달성하는 방법은 무엇입니까?


105

C #에서 Base64 URL 안전 인코딩을 달성하고 싶습니다. Java Codec에는 URL로 안전하게 인코딩 된 문자열을 제공 하는 공용 라이브러리 가 있습니다 . C #을 사용하여 어떻게 똑같이 할 수 있습니까?

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

위의 코드는이를 Base64로 변환하지만 ==. URL 안전 인코딩을 달성하는 방법이 있습니까?


그냥 Url.Encode문자열에 사용할 수 없습니까 BASE64?

C #에 어떤 네임 스페이스 Url 클래스가 있습니까?
Vishvesh Phadnis 2014 년

살펴보기 : msdn.microsoft.com/en-us/library/…System.Web 어셈블리 를 참조해야합니다 .

=를 % 3D로 변환하고 있습니다. 나는 그것을 원하지 않는다.
Vishvesh Phadnis 2014 년

3
그래서 당신은 무엇을 의미 url safe합니까? %3DURL이 안전합니다.

답변:


182

URL에서 사용 하기 위해 단순히 알파벳바꾸는 것이 일반적 이므로 % 인코딩이 필요하지 않습니다. 불과 3 65 개 문자는 문제가있다 - +, /하고 =. 가장 일반적인 교체는 -대신 +하고 _대신에 /. 패딩에 관해서는 : 그냥 제거하십시오 ( =); 필요한 패딩의 양을 추론 할 수 있습니다 . 다른 쪽 끝 : 프로세스를 반대로하십시오.

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
Common Codec에서는 URL 안전 모드로 [0-9a-zA-Z_-] 문자를 사용합니다.
Vishvesh Phadnis 2014 년

이것은 URL 응용 프로그램의 Base64에 대한 위키 페이지에서도 언급됩니다. en.wikipedia.org/wiki/Base64
wonster

2
또한이 기능은 ' stackoverflow.com/questions/1886686/… '을 사용하여 모든 노력을 수행합니다.
toy4fun

1
왜 필요하지 않은가 : 사례 1 : 수신 + = "==="; 단절; ?
alex da franca

5
@alexdafranca는 길이 mod 4 of 1을 갖지 않기 때문입니다. 3x8 비트는 4x6 비트가되고 (각 6 비트는 선택한 알파벳의 64 자 중 하나입니다), 0x8 비트는 패딩없이 0x6 비트로 인코딩되고, 1x8 비트는 다음과 같이 인코딩됩니다. ==패딩이있는 2x6 비트 , 2x8은 패딩이있는 3x6으로 인코딩되고 =, 3x8은 패딩이없는 4x6으로 인코딩 된 다음 정렬되어 반복됩니다. 1x6 비트로 인코딩 된 것은 없으므로 ===패딩이 필요하지 않습니다 .
George Helyar 19

83

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

1
이것은 받아 들인 대답보다 훨씬 깨끗합니다. 단점이 있습니까?
taktak004

18
참고 : Microsoft.IdentityModel.Tokens는 다운로드해야하는 NuGet 패키지입니다.
Uber Schnoz

나는 이것이 크로스 플랫폼이 아니라는 이름으로 가정하고 있습니다. 그럴까요?
Brandon S.


8

여기에 몇 가지 성능 개선 사항에 대한 답변을 기반 으로 GitHub (MIT 라이선스) 에서 사용할 수 있는 소스 코드 를 사용하여 매우 사용하기 쉬운 url-safe base64 구현을 NuGet 에 게시했습니다 .

사용법은 다음과 같습니다.

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

감사합니다. 당신이 선택한 왜 관심 부족 "string".Replace을위한 encode방법,하지만, 수동을 대체와 루프 decode?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

@ ᴍᴀᴛᴛʙᴀᴋᴇʀ 나는 그것을 다시 방문하고 벤치 마크를 실행해야하지만 그것은 우리가 후자에 추가하기 때문에 불변 문자열 대신 성장 가능한 문자 목록으로 표현되기 때문입니다.
Mahmoud Al-Qudsi

대신 반환 형식 = 문자열을 다른 클래스 : github.com/vndevpro/architecture-common/blob/master/...
hazjack

8

RFC4648에 따라 "base64url"이 아닌 URL 보안 base64와 유사한 인코딩을 얻으려면을 사용 System.Web.HttpServerUtility.UrlTokenEncode(bytes)하여 인코딩 및 System.Web.HttpServerUtility.UrlTokenDecode(bytes)디코딩합니다.


6
이는 RFC4648에 따른 표준 준수 URL 안전 Base64 인코딩을 제공하지 않습니다. 이 Q & A를 참조하십시오 . 주의해서 사용하십시오.
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

다음은 Marc와 동일한 방식으로 인코딩 된 url-safe base64를 디코딩하는 또 다른 방법입니다. 나는 왜 4-length%4일 했는지 모르겠다 .

다음과 같이 원점의 비트 길이 만 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

UWP에서 Microsoft 암호화 엔진 사용.

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.