문제

REGEX를 사용하여 Base64 데이터를 검증하거나 소독 할 수 있습니까? 이것이 간단한 질문이지만이 질문을 이끌어내는 요인은 어려운 이유입니다.

RFC 사양을 따를 입력 데이터에 완전히 의존 할 수없는 Base64 디코더가 있습니다. 따라서 내가 직면 한 문제는 아마도 78로 나뉘 지 않을 수있는 Base64 데이터와 같은 문제입니다 (78이라고 생각합니다. RFC를 두 번 확인해야하므로 정확한 숫자가 잘못되면 저를 지정하지 마십시오) 문자. 선이 또는 선이 CRLF에서 끝나지 않을 수 있습니다. 그 점에서 그것은 CR, LF 만 있거나 없을 수도 있습니다.

그래서 나는 Base64 데이터를 구문 분석 한 시간의 지옥을 가지고있었습니다. 이로 인해 다음과 같은 예는 안정적으로 해독하는 것이 불가능 해집니다. 간단한 부분 마임 헤더 만 표시 할 것입니다.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

좋아요, 그렇게 구문 분석은 문제가되지 않으며 정확히 우리가 기대할 수있는 결과입니다. 그리고 99%의 경우, 모든 코드를 사용하여 버퍼의 각 char가 유효한 Base64 char인지 확인합니다. 그러나 다음 예제는 렌치를 믹스에 던집니다.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

이것은 내가 일부 바이러스에서 보았던 Base64 인코딩의 버전과 일부 메일 독자를 활용하려는 다른 것들을 모든 비용으로 마임을 구문 분석하고, 책에 의해 엄격하게 진행되는 것, 또는 오히려 RFC; 당신이 할 경우.

내 Base64 디코더는 두 번째 예제를 다음 데이터 스트림으로 디코딩합니다. 그리고 여기서 명심하십시오. 원래 스트림은 모두 ASCII 데이터입니다!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

누구든지 한 번에 두 가지 문제를 해결할 수있는 좋은 방법이 있습니까? 다른 규칙이 적용된 데이터에 대해 두 가지 변환을 수행하고 결과를 비교하는 것 외에는 가능하지는 않습니다. 그러나 그 접근 방식을 취하면 어떤 출력을 신뢰합니까? ASCII 휴리스틱은 베스트 솔루션, 그러나이 코드가 실제로 관여하는 바이러스 스캐너만큼 복잡한 코드, 실행 시간 및 복잡성이 얼마나 되는가? 허용 가능한 Base64와 그렇지 않은 것을 배우기 위해 휴리스틱 엔진을 어떻게 훈련시킬 것입니까?


업데이트:

이 질문이 계속되고있는 견해의 수에 따라, 나는 수십만 건의 거래와 함께 3 년 동안 C# 응용 프로그램에서 사용했던 간단한 정규를 게시하기로 결정했습니다. 솔직히, 나는 주어진 답을 좋아한다 검보 최고는 내가 선택한 대답으로 선택한 이유입니다. 그러나 C#을 사용하고 적어도 문자열 또는 바이트 []에 유효한 Base64 데이터가 포함되어 있는지 여부를 감지 할 수있는 매우 빠른 방법을 찾고있는 사람에게는 다음과 같은 것이 나에게 매우 잘 작동하는 것을 발견했습니다.

[^-A-Za-z0-9+/=]|=[^=]|={3,}$

그리고 네, 이것은 단지 a를위한 것입니다 Base64 데이터의 적절한 형식이 아닙니다 RFC1341 메시지. 따라서이 유형의 데이터를 다루는 경우 위의 정규를 사용하기 전에이를 고려하십시오. 다른 목적 (URL, 파일 이름, XML 인코딩 등)을 위해 Base16, Base32, Radix 또는 Base64를 다루는 경우 다음과 같습니다. 고도로 읽는 것이 좋습니다 RFC4648 저것 검보 이 질문/답변 세트에서 제안을 사용하기 전에 구현에 사용 된 숯불 및 터미네이터를 잘 알고 있어야한다고 그의 대답에 언급되었습니다.

도움이 되었습니까?

해결책

로부터 RFC 4648:

기본 데이터 인코딩은 많은 상황에서 유산의 이유로 미국 ASCII 데이터로 제한되는 환경에서 데이터를 저장하거나 전송하는 데 사용됩니다.

따라서 데이터가 위험한 것으로 간주되는 경우 인코딩 된 데이터의 사용 목적에 따라 다릅니다.

그러나 Base64 인코딩 된 단어와 일치하는 정규 표현식을 찾고 있다면 다음을 사용할 수 있습니다.

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

다른 팁

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

이것은 좋지만 빈 줄과 일치합니다.

이것은 빈 문자열과 일치하지 않습니다.

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$

둘 다 ":"또는 A"."유효한 Base64에 나타날 것입니다. http://www.stackoverflow.com 선. Perl에서는 같은 것입니다

my $sanitized_str = join q{}, grep {!/[^A-Za-z0-9+\/=]/} split /\n/, $str;

say decode_base64($sanitized_str);

당신이 원하는 것일 수 있습니다. 그것은 생산됩니다

이것은 stackoverflow exmaple에 대한 간단한 ASCII Base64입니다.

지금까지 찾을 수있는 최고의 Regexp는 여기에 있습니다.https://www.npmjs.com/package/base64-regex

현재 버전에있는 것은 다음과 같습니다.

module.exports = function (opts) {
  opts = opts || {};
  var regex = '(?:[A-Za-z0-9+\/]{4}\\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)';

  return opts.exact ? new RegExp('(?:^' + regex + '$)') :
                    new RegExp('(?:^|\\s)' + regex, 'g');
};
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top