Bagaimana cara memeriksa apakah suatu string Base64 dikodekan atau tidak


194

Saya ingin mendekodekan string yang disandikan Base64, lalu menyimpannya di basis data saya. Jika inputnya tidak di-encode Base64, saya perlu melakukan kesalahan.

Bagaimana saya bisa mengecek apakah suatu string di-base64?


Mengapa? Bagaimana situasinya dapat muncul?
Marquis of Lorne

2
tanpa menentukan bahasa pemrograman mana (dan / atau) Sistem Operasi yang Anda targetkan, ini adalah pertanyaan yang sangat terbuka
bcarroll

5
Yang dapat Anda tentukan adalah bahwa string tersebut hanya berisi karakter yang valid untuk string yang disandikan base64. Mungkin tidak mungkin untuk menentukan bahwa string adalah versi yang disandikan base64 dari beberapa data. misalnya test1234adalah string yang disandikan base64 yang valid, dan ketika Anda mendekodekannya Anda akan mendapatkan beberapa byte. Tidak ada aplikasi cara independen untuk menyimpulkan bahwa test1234bukan string yang disandikan base64.
Kinjal Dixit

Jawaban:


249

Anda dapat menggunakan ekspresi reguler berikut untuk memeriksa apakah string dikodekan base64 atau tidak:

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

Dalam pengkodean base64, set karakter adalah [A-Z, a-z, 0-9, and + /]. Jika panjang istirahat kurang dari 4, string diisi dengan '='karakter.

^([A-Za-z0-9+/]{4})* berarti string dimulai dengan 0 grup base64 atau lebih.

([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$berarti ujung string dalam salah satu dari tiga bentuk: [A-Za-z0-9+/]{4}, [A-Za-z0-9+/]{3}=atau [A-Za-z0-9+/]{2}==.


10
Hanya ingin memverifikasi, jadi tolong bantu dengan pertanyaan saya: Apa jaminan bahwa regex ini akan selalu merujuk hanya string base64 ?? Jika ada string yang tidak memiliki ruang dan itu adalah kelipatan dari 4 karakter, maka apakah string itu akan dianggap sebagai string base64 ????
DShah

3
Maka itu adalah string base64 yang valid yang dapat diterjemahkan. Anda bisa menambahkan batasan panjang minimum; misalnya, alih-alih nol atau lebih pengulangan dari kelompok empat, minta (katakanlah) empat atau lebih. Itu tergantung pada masalah Anda juga; jika pengguna Anda sering memasukkan satu kata dalam bahasa dengan kata-kata yang panjang dan ASCII murni (Hawaii?) lebih rentan kesalahan daripada jika input non-base64 biasanya berisi spasi, tanda baca, dll.
tripleee

62
Ini hanya memberi tahu bahwa suatu input bisa saja merupakan nilai yang dikodekan b64, tetapi itu tidak memberi tahu apakah input tersebut sebenarnya adalah nilai yang dikodekan b64. Dengan kata lain, abcdakan cocok, tetapi itu tidak selalu mewakili nilai yang dikodekan dari sekadar abcdinput biasa
Tzury Bar Yochay

3
Regexp Anda salah, karena tidak cocok dengan string kosong, dengan adalah base64 pengkodean data biner nol-panjang menurut RFC 4648.
kemerahan

5
@Adomas, "pass" adalah string base64 yang benar-benar valid, yang menerjemahkan ke dalam urutan byte 0xa5, 0xabdan 0x2c. Mengapa membuangnya secara apriori , jika Anda tidak memiliki konteks untuk memutuskan?
Luis Colorado

50

Jika Anda menggunakan Java, Anda sebenarnya dapat menggunakan perpustakaan commons-codec

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

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

17
dari dokumentasi: isArrayByteBase64(byte[] arrayOctet)Sudah usang. 1.5 Penggunaan isBase64(byte[]), akan dihapus dalam 2.0.
Avinash R

7
Anda dapat menggunakan juga Base64.isBase64 (String base64) alih-alih mengubahnya sendiri ke byte array.
Sasa

5
Sedihnya, berdasarkan pada dokumentasi: commons.apache.org/proper/commons-codec/apidocs/org/apache/… : "Menguji String yang diberikan untuk melihat apakah itu berisi hanya karakter yang valid dalam alfabet Base64. Saat ini metode memperlakukan spasi putih sebagai sah." Ini berarti bahwa metode ini memiliki beberapa positif palsu seperti "spasi putih" atau angka ("0", "1").
Christian Vielma

untuk string Base64.isBase64 (konten)
ema

3
Jawaban ini salah karena diberikan stringToBeChecked="some plain text"maka itu menetapkan boolean isBase64=truemeskipun itu bukan nilai yang disandikan Base64. Baca sumber untuk commons-codec-1.4 Base64.isArrayByteBase64()hanya memeriksa bahwa setiap karakter dalam string valid untuk dipertimbangkan untuk pengkodean Base64 dan memungkinkan ruang putih.
Brad

49

Anda bisa:

  • Pastikan panjangnya adalah kelipatan 4 karakter
  • Periksa bahwa setiap karakter ada di set AZ, az, 0-9, +, / kecuali untuk padding di bagian akhir yaitu 0, 1 atau 2 '=' karakter

Jika Anda mengharapkan bahwa itu akan menjadi base64, maka Anda mungkin bisa menggunakan pustaka apa saja yang tersedia di platform Anda untuk mencoba mendekodekannya ke array byte, melemparkan pengecualian jika itu bukan basis 64 yang valid. Itu tergantung pada platform Anda, tentu saja.


Parsing berbeda dari validasi setidaknya oleh fakta bahwa ia membutuhkan memori untuk byte array yang didekodekan. Jadi ini bukan pendekatan yang paling efektif dalam beberapa kasus.
Victor Yarema

1
@VictorYarema: Saya menyarankan pendekatan validasi saja (poin-poin) dan juga pendekatan parsing (setelah poin-poin).
Jon Skeet

16

Pada Java 8, Anda cukup menggunakan java.util.Base64 untuk mencoba dan mendekode string:

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

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

3
ya, itu sebuah pilihan, tetapi jangan lupa bahwa tangkapan adalah operasi yang cukup mahal di Jawa
panser

2
Bukan itu masalahnya lagi. Penanganan pengecualian berjalan cukup baik. Anda sebaiknya tidak lupa bahwa Java Regex sangat lambat. Maksud saya: BENAR-BENAR LAMBAT! Ini sebenarnya lebih cepat untuk memecahkan kode Base64 dan memeriksa apakah itu (tidak) berfungsi daripada mencocokkan String dengan Regex di atas. Saya melakukan tes kasar dan pencocokan Java Regex sekitar enam kali lebih lambat (!!) daripada menangkap pengecualian akhirnya pada decode.
Sven Döring

Dengan lebih banyak tes berjalan sebenarnya sebelas kali lebih lambat. Saatnya untuk implementasi Regex yang lebih baik di Jawa. Bahkan pemeriksaan Regex dengan mesin JavaScript Nashorn di Jawa jauh lebih cepat. Luar biasa. Selain itu JavaScript Regex (dengan Nashorn) jauh lebih kuat.
Sven Döring

3
Dengan Java 11 (bukan Java 8) pemeriksaan Regex bahkan 22 kali lebih lambat. 🤦 (Karena decoding Base64 menjadi lebih cepat.)
Sven Döring

15

Coba seperti ini untuk 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"; 
}

Gunakan ini untuk 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
Bahasa apa ini? Pertanyaan itu diajukan tanpa merujuk ke bahasa
Ozkan

ini tidak akan berhasil. baca docs Returns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley

1
Bagaimana? jika input mengandung karakter luar maka itu bukan base64, kan?
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

Periksa untuk melihat JIKA panjang string adalah kelipatan dari 4. Setelah itu gunakan regex ini untuk memastikan semua karakter dalam string adalah karakter base64.

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

Jika pustaka yang Anda gunakan menambahkan baris baru sebagai cara mengamati 76 maks karakter per baris, gantikan dengan string kosong.


Tautan yang disebutkan menunjukkan 404. Silakan periksa dan perbarui.
Ankur

Maaf @AnkurKumar tetapi itulah yang terjadi ketika orang-orang memiliki URL yang tidak keren: mereka berubah setiap saat. Saya tidak tahu ke mana ia dipindahkan. Saya harap Anda menemukan sumber daya lain yang bermanfaat melalui Google
Yaw Boakye

Anda selalu bisa mendapatkan halaman lama dari web.archive.org - inilah url aslinya. web.archive.org/web/20120919035911/http://… atau saya memposting teks di sini: gist.github.com/mika76/d09e2b65159e435e7a4cc5b0299c3e84
Mladen Mihajlovic

4

Ada banyak varian Base64 , jadi pertimbangkan untuk menentukan apakah string Anda menyerupai varian yang ingin Anda tangani. Dengan demikian, Anda mungkin perlu menyesuaikan regex di bawah ini sehubungan dengan indeks dan padding karakter (yaitu +, /, =).

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

Pemakaian:

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

3

Coba ini:

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

Tidak mungkin untuk memeriksa apakah string base64 dikodekan atau tidak. Itu hanya mungkin untuk memvalidasi jika string itu dari format string yang dienkode base64, yang berarti bahwa itu bisa menjadi string yang dihasilkan oleh pengkodean base64 (untuk memeriksa bahwa, string dapat divalidasi terhadap regexp atau perpustakaan dapat digunakan, banyak jawaban lain untuk pertanyaan ini memberikan cara yang baik untuk memeriksa ini, jadi saya tidak akan menjelaskan lebih lanjut).

Sebagai contoh, string flowadalah string yang disandikan base64 yang valid. Tetapi tidak mungkin untuk mengetahui apakah itu hanya string sederhana, kata bahasa Inggris flow, atau basis 64 string yang disandikan~Z0


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

ekspresi reguler ini membantu saya mengidentifikasi base64 dalam aplikasi saya di rails, saya hanya punya satu masalah, itu adalah mengenali string "errorDescripcion", saya menghasilkan kesalahan, untuk menyelesaikannya hanya memvalidasi panjang string.


Regex di atas /^.....$/.match(my_string) memberikan kesalahan pemformatan dengan mengatakan 'Penutupan tak tertandingi' '
james2611nov

Dan dengan 'prematur akhir char-class: / ^ (([A-Za-z0-9 + /' kesalahan sintaks.
james2611nov

Nevermind memperbaikinya dengan menambahkan \ di depan setiap / karakter.
james2611nov

errorDescriptionadalah base64 string yang valid, itu menerjemahkan ke dalam urutan biner byte (dalam hex): 7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27.
Luis Colorado

Ini bekerja sempurna bagi saya untuk memeriksa string yang disandikan base64.
Deepak Lakhara

1

Ini berfungsi dalam 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.")

Ringkasan: IsBase64("string here") mengembalikan true jika string heredikodekan Base64, dan itu mengembalikan false jika string hereTIDAK dikodekan Base64.


1

C # Ini berkinerja bagus:

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
Merekomendasikan untuk beralih bahasa pemrograman untuk menyelesaikan masalah secara umum bukan respons yang valid.
Luis Colorado

0

Tidak ada cara untuk membedakan string dan base64, kecuali string di sistem Anda memiliki beberapa batasan atau identifikasi tertentu.


0

Cuplikan ini mungkin berguna saat Anda mengetahui panjang konten asli (mis. Checksum). Itu memeriksa bahwa bentuk disandikan memiliki panjang yang benar.

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

Jika RegEx tidak berfungsi dan Anda tahu gaya format string asli, Anda bisa membalikkan logikanya, dengan regexing untuk format ini.

Sebagai contoh saya bekerja dengan file xml yang disandikan base64 dan hanya memeriksa apakah file tersebut berisi markup xml yang valid. Jika tidak saya dapat berasumsi, bahwa itu base64 diterjemahkan. Ini tidak terlalu dinamis tetapi berfungsi baik untuk aplikasi kecil saya.


0

Ini berfungsi dalam 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

Coba ini menggunakan regex yang disebutkan sebelumnya:

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

... Kami juga dapat membuat validasi sederhana seperti, jika memiliki spasi tidak boleh 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, bisakah Anda memberikan solusi?
Marco

0

jika saat decoding kita mendapatkan string dengan karakter ASCII, maka string itu tidak dikodekan

(RoR) solusi 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

Saya mencoba menggunakan ini, ya ini berhasil

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

tapi saya menambahkan syarat untuk memeriksa setidaknya karakter adalah =

string.lastIndexOf("=") >= 0

Mengapa memeriksa =: Spesifikasi apa Base64yang Anda gunakan? Apa end of the characterartinya, dan bagaimana lastIndexOf()pemeriksaan non-negatif itu?
greybeard
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.