Cách kiểm tra xem một chuỗi có được mã hóa Base64 hay không


194

Tôi muốn giải mã một chuỗi mã hóa Base64, sau đó lưu trữ nó trong cơ sở dữ liệu của tôi. Nếu đầu vào không được mã hóa Base64, tôi cần ném lỗi.

Làm cách nào để kiểm tra xem một chuỗi có được mã hóa Base64 không?


Tại sao? Làm thế nào tình hình có thể phát sinh?
Hầu tước Lorne

2
mà không chỉ định ngôn ngữ lập trình (và / hoặc) Hệ điều hành nào bạn đang nhắm mục tiêu, đây là một câu hỏi rất mở
bcarroll

5
Tất cả những gì bạn có thể xác định là chuỗi chỉ chứa các ký tự hợp lệ cho chuỗi được mã hóa base64. Có thể không xác định được rằng chuỗi là phiên bản được mã hóa cơ sở64 của một số dữ liệu. ví dụ test1234là một chuỗi được mã hóa base64 hợp lệ và khi bạn giải mã nó, bạn sẽ nhận được một số byte. Không có cách kết luận độc lập nào về ứng dụng mà test1234không phải là chuỗi được mã hóa base64.
Kinjal Dixit

Câu trả lời:


249

Bạn có thể sử dụng biểu thức chính quy sau để kiểm tra xem một chuỗi có được mã hóa base64 hay không:

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

Trong mã hóa base64, bộ ký tự là [A-Z, a-z, 0-9, and + /]. Nếu độ dài phần còn lại nhỏ hơn 4, chuỗi được đệm bằng các '='ký tự.

^([A-Za-z0-9+/]{4})* có nghĩa là chuỗi bắt đầu với 0 hoặc nhiều nhóm base64.

([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$có nghĩa là chuỗi kết thúc ở một trong ba dạng : [A-Za-z0-9+/]{4}, [A-Za-z0-9+/]{3}=hoặc [A-Za-z0-9+/]{2}==.


10
Chỉ muốn xác minh vì vậy hãy giúp tôi với câu hỏi của tôi: Điều gì đảm bảo rằng regex này sẽ luôn chỉ đề cập đến chuỗi base64 ?? Nếu có bất kỳ chuỗi nào không có khoảng trắng và nó có nhiều 4 ký tự thì chuỗi đó có được coi là chuỗi base64 không ????
DShah

3
Sau đó, nó là một chuỗi base64 hợp lệ có thể được giải mã. Bạn có thể thêm một ràng buộc độ dài tối thiểu; ví dụ, thay vì không hoặc nhiều lần lặp lại của nhóm bốn, yêu cầu (nói) bốn hoặc nhiều hơn. Nó phụ thuộc vào vấn đề của bạn, quá; nếu người dùng của bạn thường nhập một từ duy nhất trong một ngôn ngữ có các từ dài và ASCII thuần túy (tiếng Hawaii?) thì nó sẽ dễ bị lỗi hơn so với nếu đầu vào không phải là cơ sở64 thường có dấu cách, dấu chấm câu, v.v.
tripleee

62
Điều này chỉ nói rằng đầu vào có thể là giá trị được mã hóa b64, nhưng nó không cho biết đầu vào thực sự là giá trị được mã hóa b64 hay không . Nói cách khác, abcdsẽ khớp, nhưng nó không nhất thiết phải đại diện cho giá trị được mã hóa thay vì chỉ là một abcdđầu vào đơn giản
Tzury Bar Yochay

3
Regrec của bạn không chính xác, vì nó không khớp với chuỗi trống, với mã hóa cơ sở64 của dữ liệu nhị phân có độ dài bằng 0 theo RFC 4648.
đỏ

5
@Adomas, "pass" là một chuỗi base64 hoàn toàn hợp lệ, mà giải mã thành chuỗi các byte 0xa5, 0xab0x2c. Tại sao phải loại bỏ nó trước , nếu bạn không có nhiều bối cảnh để quyết định?
Luis Colorado

50

Nếu bạn đang sử dụng Java, bạn thực sự có thể sử dụng thư viện commons-codec

import org.apache.commons.codec.binary.Base64;

String stringToBeChecked = "...";
boolean isBase64 = Base64.isArrayByteBase64(stringToBeChecked.getBytes());

17
từ tài liệu: isArrayByteBase64(byte[] arrayOctet)Không dùng nữa. 1.5 Sử dụng isBase64(byte[]), sẽ bị xóa trong 2.0.
Avinash R

7
Bạn cũng có thể sử dụng Base64.isBase64 (Chuỗi base64) thay vì tự chuyển đổi nó thành mảng byte.
Sasa

5
Đáng buồn thay, dựa trên tài liệu: commons.apache.org/proper/commons-codec/apidocs/org/apache/ . có hiệu lực." Điều này có nghĩa là phương thức này có một số dương tính giả như "khoảng trắng" hoặc số ("0", "1").
Christian Vielma

cho chuỗi Base64.isBase64 (nội dung)
ema

3
Câu trả lời này là sai vì được đưa ra stringToBeChecked="some plain text"sau đó nó đặt boolean isBase64=truemặc dù đó không phải là giá trị được mã hóa Base64. Đọc nguồn cho commons-codec-1.4, Base64.isArrayByteBase64()nó chỉ kiểm tra xem mỗi ký tự trong chuỗi có hợp lệ để được xem xét cho mã hóa Base64 và cho phép khoảng trắng.
Brad

49

Bạn có thể:

  • Kiểm tra xem độ dài có phải là bội số của 4 ký tự không
  • Kiểm tra xem mọi ký tự có trong tập hợp AZ, az, 0-9, +, / ngoại trừ phần đệm ở cuối là 0, 1 hoặc 2 '=' ký tự

Nếu bạn đang mong đợi rằng nó sẽ là base64, thì có lẽ bạn chỉ cần sử dụng bất kỳ thư viện nào có sẵn trên nền tảng của mình để cố gắng giải mã nó thành một mảng byte, ném một ngoại lệ nếu đó không phải là cơ sở 64 hợp lệ. Điều đó phụ thuộc vào nền tảng của bạn, tất nhiên.


Phân tích cú pháp khác với xác nhận ít nhất bởi thực tế là nó yêu cầu bộ nhớ cho mảng byte được giải mã. Vì vậy, đây không phải là cách tiếp cận hiệu quả nhất trong một số trường hợp.
Victor Yarema

1
@VictorYarema: Tôi đã đề xuất cả cách tiếp cận chỉ xác thực (điểm đạn) và cũng là cách tiếp cận phân tích cú pháp (sau điểm đạn).
Jon Skeet

16

Kể từ Java 8, bạn chỉ cần sử dụng java.util.Base64 để thử và giải mã chuỗi:

String someString = "...";
Base64.Decoder decoder = Base64.getDecoder();

try {
    decoder.decode(someString);
} catch(IllegalArgumentException iae) {
    // That string wasn't valid.
}

3
vâng, đó là một tùy chọn, nhưng đừng quên rằng hoạt động khai thác khá tốn kém trong Java
panser

2
Đó không phải là trường hợp nữa. Xử lý ngoại lệ đang thực hiện khá tốt. Bạn tốt hơn đừng quên rằng Java Regex khá chậm. Ý tôi là: THẬT SỰ CHẬM! Thật sự nhanh hơn để giải mã Base64 và kiểm tra xem nó có hoạt động không thay vì khớp với Chuỗi với Regex ở trên. Tôi đã thực hiện một thử nghiệm sơ bộ và kết hợp Java Regex chậm hơn khoảng sáu lần (!!) so với việc bắt một ngoại lệ cuối cùng trên giải mã.
Sven Döring

Với nhiều lần chạy thử, nó thực sự chậm hơn mười một lần. Đã đến lúc triển khai Regex tốt hơn trong Java. Ngay cả một kiểm tra Regex với công cụ JavaScript Nashorn trong Java cũng nhanh hơn rất nhiều. Không thể tin được. Ngoài ra, JavaScript Regex (với Nashorn) mạnh hơn rất nhiều.
Sven Döring

3
Với Java 11 (thay vì Java 8), kiểm tra Regex thậm chí còn chậm hơn 22 lần. (Vì quá trình giải mã Base64 nhanh hơn.)
Sven Döring

15

Hãy thử như thế này cho PHP5

//where $json is some data that can be base64 encoded
$json=some_data;

//this will check whether data is base64 encoded or not
if (base64_decode($json, true) == true)
{          
   echo "base64 encoded";          
}
else 
{
   echo "not base64 encoded"; 
}

Sử dụng cái này cho PHP7

 //$string parameter can be base64 encoded or not

function is_base64_encoded($string){
 //this will check if $string is base64 encoded and return true, if it is.
 if (base64_decode($string, true) !== false){          
   return true;        
 }else{
   return false;
 }
}

1
Ngôn ngữ này là gì? Câu hỏi đã được hỏi mà không đề cập đến một ngôn ngữ
Ozkan

Điều này sẽ không hoạt động. đọc tài liệu Returns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley

1
Làm sao? Nếu đầu vào chứa ký tự bên ngoài thì nó không phải là base64, phải không?
Suneel Kumar

6
var base64Rejex = /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i;
var isBase64Valid = base64Rejex.test(base64Data); // base64Data is the base64 string

if (isBase64Valid) {
    // true if base64 formate
    console.log('It is base64');
} else {
    // false if not in base64 formate
    console.log('it is not in base64');
}

5

Kiểm tra xem NẾU độ dài của chuỗi là bội số của 4. Sau khi sử dụng biểu thức chính này để đảm bảo tất cả các ký tự trong chuỗi là ký tự base64.

\A[a-zA-Z\d\/+]+={,2}\z

Nếu thư viện bạn sử dụng thêm một dòng mới như một cách quan sát 76 ký tự tối đa trên mỗi quy tắc dòng, hãy thay thế chúng bằng các chuỗi trống.


Liên kết được đề cập cho thấy 404. Vui lòng kiểm tra và cập nhật.
Ankur

Xin lỗi @AnkurKumar nhưng đó là những gì xảy ra khi mọi người có URL không lưu trữ: họ thay đổi mọi lúc. Tôi không biết nó chuyển đến đâu. Tôi hy vọng bạn tìm thấy các tài nguyên hữu ích khác thông qua Google
Yaw Boakye

Bạn luôn có thể lấy các trang cũ từ web.archive.org - đây là url gốc. web.archive.org/web/20120919035911/http://... hoặc tôi gửi văn bản ở đây: gist.github.com/mika76/d09e2b65159e435e7a4cc5b0299c3e84
Mladen Mihajlovic

4

Có nhiều biến thể của Base64 , vì vậy hãy xem xét việc xác định xem chuỗi của bạn có giống với biến bạn muốn xử lý hay không. Như vậy, bạn có thể cần phải điều chỉnh regex dưới đây liên quan đến chỉ số và đệm ký tự (ví dụ +, /, =).

class String
  def resembles_base64?
    self.length % 4 == 0 && self =~ /^[A-Za-z0-9+\/=]+\Z/
  end
end

Sử dụng:

raise 'the string does not resemble Base64' unless my_string.resembles_base64?

3

Thử cái này:

public void checkForEncode(String string) {
    String pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
    Pattern r = Pattern.compile(pattern);
    Matcher m = r.matcher(string);
    if (m.find()) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }
}

3

Không thể kiểm tra xem một chuỗi có được mã hóa base64 hay không. Chỉ có thể xác thực nếu chuỗi đó có định dạng chuỗi được mã hóa base64, điều đó có nghĩa là chuỗi đó được tạo bởi mã hóa base64 (để kiểm tra xem, chuỗi có thể được xác thực dựa trên regrec hay thư viện có thể được sử dụng không, nhiều các câu trả lời khác cho câu hỏi này cung cấp những cách tốt để kiểm tra điều này, vì vậy tôi sẽ không đi vào chi tiết).

Ví dụ, chuỗi flowlà một chuỗi được mã hóa base64 hợp lệ. Nhưng không thể biết đó chỉ là một chuỗi đơn giản, một từ tiếng Anh flowhay là chuỗi 64 được mã hóa cơ sở~Z0


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

biểu thức chính quy này đã giúp tôi xác định base64 trong ứng dụng của mình trong rails, tôi chỉ gặp một vấn đề, đó là nó nhận ra chuỗi "errorDescripcion", tôi tạo ra một lỗi, để giải quyết nó chỉ xác nhận độ dài của chuỗi.


Regex ở trên / ^ ^ .$ /.match (my_opes) gây ra lỗi định dạng bằng cách nói 'Đóng không
khớp

Và với 'kết thúc sớm của lớp char: / ^ (([A-Za-z0-9 + /' lỗi cú pháp.
james2611nov

Nevermind đã sửa nó bằng cách thêm \ vào trước mỗi / ký tự.
james2611nov

errorDescriptionlà một chuỗi base64 hợp lệ, nó giải mã thành chuỗi nhị phân của byte (ở dạng hex) : 7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27.
Luis Colorado

Nó hoạt động hoàn hảo đối với tôi để kiểm tra chuỗi mã hóa base64.
Deepak Lakhara

1

Điều này hoạt động trong Python:

import base64

def IsBase64(str):
    try:
        base64.b64decode(str)
        return True
    except Exception as e:
        return False

if IsBase64("ABC"):
    print("ABC is Base64-encoded and its result after decoding is: " + str(base64.b64decode("ABC")).replace("b'", "").replace("'", ""))
else:
    print("ABC is NOT Base64-encoded.")

if IsBase64("QUJD"):
    print("QUJD is Base64-encoded and its result after decoding is: " + str(base64.b64decode("QUJD")).replace("b'", "").replace("'", ""))
else:
    print("QUJD is NOT Base64-encoded.")

Tóm tắt: IsBase64("string here") trả về true nếu string heređược mã hóa Base64 và nó trả về false nếu string hereKHÔNG được mã hóa Base64.


1

C # Điều này đang thực hiện tuyệt vời:

static readonly Regex _base64RegexPattern = new Regex(BASE64_REGEX_STRING, RegexOptions.Compiled);

private const String BASE64_REGEX_STRING = @"^[a-zA-Z0-9\+/]*={0,3}$";

private static bool IsBase64(this String base64String)
{
    var rs = (!string.IsNullOrEmpty(base64String) && !string.IsNullOrWhiteSpace(base64String) && base64String.Length != 0 && base64String.Length % 4 == 0 && !base64String.Contains(" ") && !base64String.Contains("\t") && !base64String.Contains("\r") && !base64String.Contains("\n")) && (base64String.Length % 4 == 0 && _base64RegexPattern.Match(base64String, 0).Success);
    return rs;
}

1
Console.WriteLine("test".IsBase64()); // true
Langdon

2
Đề nghị chuyển ngôn ngữ lập trình để giải quyết vấn đề nói chung không phải là một phản hồi hợp lệ.
Luis Colorado

0

Không có cách nào để phân biệt chuỗi và base64 được mã hóa, ngoại trừ chuỗi trong hệ thống của bạn có một số giới hạn hoặc nhận dạng cụ thể.


0

Đoạn mã này có thể hữu ích khi bạn biết độ dài của nội dung gốc (ví dụ: tổng kiểm tra). Nó kiểm tra hình thức được mã hóa có độ dài chính xác.

public static boolean isValidBase64( final int initialLength, final String string ) {
  final int padding ;
  final String regexEnd ;
  switch( ( initialLength ) % 3 ) {
    case 1 :
      padding = 2 ;
      regexEnd = "==" ;
      break ;
    case 2 :
      padding = 1 ;
      regexEnd = "=" ;
      break ;
    default :
      padding = 0 ;
      regexEnd = "" ;
  }
  final int encodedLength = ( ( ( initialLength / 3 ) + ( padding > 0 ? 1 : 0 ) ) * 4 ) ;
  final String regex = "[a-zA-Z0-9/\\+]{" + ( encodedLength - padding ) + "}" + regexEnd ;
  return Pattern.compile( regex ).matcher( string ).matches() ;
}

0

Nếu RegEx không hoạt động và bạn biết kiểu định dạng của chuỗi gốc, bạn có thể đảo ngược logic, bằng cách biểu thức lại cho định dạng này.

Ví dụ: tôi làm việc với các tệp xml được mã hóa base64 và chỉ cần kiểm tra xem tệp có chứa đánh dấu xml hợp lệ không. Nếu tôi không thể giả sử, thì nó đã được giải mã. Điều này không phải là rất năng động nhưng hoạt động tốt cho ứng dụng nhỏ của tôi.


0

Điều này hoạt động trong Python:

def is_base64(string):
    if len(string) % 4 == 0 and re.test('^[A-Za-z0-9+\/=]+\Z', string):
        return(True)
    else:
        return(False)

0

Hãy thử điều này bằng cách sử dụng regex đã đề cập trước đó:

String regex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
if("TXkgdGVzdCBzdHJpbmc/".matches(regex)){
    System.out.println("it's a Base64");
}

... Chúng tôi cũng có thể thực hiện xác nhận đơn giản như, nếu nó có khoảng trắng thì không thể là Base64:

String myString = "Hello World";
 if(myString.contains(" ")){
   System.out.println("Not B64");
 }else{
    System.out.println("Could be B64 encoded, since it has no spaces");
 }

Ok, bạn có thể vui lòng cho một giải pháp sau đó?
Marco

0

Nếu khi giải mã chúng ta nhận được một chuỗi có các ký tự ASCII, thì chuỗi đó không được mã hóa

(RoR) dung dịch ruby:

def encoded?(str)
  Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count.zero?
end

def decoded?(str)
  Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count > 0
end

0

Tôi cố gắng sử dụng cái này, vâng cái này nó hoạt động

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

nhưng tôi đã thêm vào điều kiện để kiểm tra ít nhất kết thúc của ký tự là =

string.lastIndexOf("=") >= 0

Tại sao phải kiểm tra =: Thông số kỹ thuật của Base64bạn đang sử dụng? Điều đó end of the charactercó nghĩa là gì , và làm thế nào để lastIndexOf()kiểm tra không tiêu cực ?
greybeard
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.