文字列がBase64エンコードされているかどうかを確認する方法


194

Base64でエンコードされた文字列をデコードし、データベースに保存したい。入力がBase64エンコードされていない場合、エラーをスローする必要があります。

文字列がBase64でエンコードされているかどうかを確認するにはどうすればよいですか?


どうして?どのようにしてこの状況が起こりますか?
ローンの侯爵

2
ターゲットとするプログラミング言語(および/または)オペレーティングシステムを指定せずに、これは非常にオープンな質問です
bcarroll

5
判断できるのは、文字列には、base64エンコードされた文字列に有効な文字のみが含まれているということです。文字列が一部のデータのbase64でエンコードされたバージョンであると判断できない場合があります。たとえばtest1234、base64でエンコードされた有効な文字列であり、デコードすると数バイトが得られます。test1234base64でエンコードされた文字列でないと結論付けるアプリケーションに依存しない方法はありません。
Kinjal Dixit 2016

回答:


249

次の正規表現を使用して、文字列がbase64でエンコードされているかどうかを確認できます。

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

base64エンコーディングでは、文字セットは[A-Z, a-z, 0-9, and + /]です。残りの長さが4未満の場合、文字列には文字が埋め込まれ'='ます。

^([A-Za-z0-9+/]{4})* 文字列が0個以上のbase64グループで始まることを意味します。

([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$3つのいずれかの形式で文字列の終了を意味します[A-Za-z0-9+/]{4}[A-Za-z0-9+/]{3}=または[A-Za-z0-9+/]{2}==


10
確認したかったので、私の質問にご協力ください:この正規表現が常にbase64文字列のみを参照することの保証は何ですか?スペースのない文字列があり、4文字の倍数である場合、その文字列はbase64文字列と見なされますか????
DShah

3
次に、デコードできる有効なbase64文字列です。最小の長さの制約を追加できます。たとえば、4つのグループの0回以上の繰り返しではなく、(たとえば)4回以上の繰り返しが必要です。それはあなたの問題にも依存します。ユーザーが長い単語と純粋なASCII(ハワイ語?)を含む言語で単一の単語を頻繁に入力する場合、base64以外の入力に通常スペースや句読点などが含まれる場合よりもエラーが発生しやすくなります
tripleee

62
これは、入力 b64エンコードされた値である可能性があることを通知するだけですが、入力実際にb64エンコードされた値であるかどうかは通知しません。言い換えると、abcdは一致しますが、必ずしも単なるabcd入力のエンコードされた値を表すとは限りません
Tzury Bar Yochay

3
あなたの正規表現は、それが空の文字列と一致しないので、間違っている、とRFC 4648.に従ってゼロ長のバイナリデータのBase64エンコーディングである
赤みがかった

5
@Adomasは、"pass" バイトシーケンスにデコード完全に有効なbase64文字列、である0xa50xab0x2c。決定するコンテキストがない場合なぜアプリオリにそれを破棄するのですか?
Luis Colorado

50

Javaを使用している場合、実際にはcommons-codecライブラリを使用できます

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

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

17
ドキュメントから:非 isArrayByteBase64(byte[] arrayOctet)推奨。1.5の使用isBase64(byte[])。2.0で削除されます。
Avinash R

7
自分でバイト配列に変換する代わりに、Base64.isBase64(String base64)を使用することもできます。
ササ

5
残念ながら、ドキュメントに基づいています:commons.apache.org/proper/commons-codec/apidocs/org/apache/…: "Base64アルファベット内に有効な文字のみが含まれているかどうかを確認するために、指定された文字列をテストします。現在、メソッドは空白を有効です。」つまり、このメソッドには、「空白」または数値(「0」、「1」)などのいくつかの誤検知があります。
クリスチャンビエルマ2015

文字列Base64.isBase64(コンテンツ)について
EMA

3
この答えは間違っています。与えられたstringToBeChecked="some plain text"場合boolean isBase64=true、Base64エンコードされた値ではありませんが設定されます。commons-codec-1.4のソースを読んBase64.isArrayByteBase64()で、文字列の各文字がBase64エンコーディングで考慮されるのに有効であり、空白が許可されていることを確認するだけです。
ブラッド

49

よくできます:

  • 長さが4文字の倍数であることを確認してください
  • すべての文字がAZ、az、0-9、+、/のセットに含まれていることを確認してください

base64 になると予想している場合は、プラットフォームで使用可能なライブラリを使用してバイト配列にデコードしようとすることができます。これが有効なbase 64でない場合は例外をスローします。これはプラットフォームによって異なります。もちろん。


解析は、少なくともデコードされたバイト配列にメモリを必要とするという点で検証とは異なります。したがって、これはいくつかのケースで最も効果的なアプローチではありません。
Victor Yarema

1
@VictorYarema:検証のみのアプローチ(箇条書き)と解析のアプローチ(箇条書きの後)の両方を提案しました。
Jon Skeet

16

Java 8以降では、java.util.Base64を使用して、文字列をデコードすることができます。

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

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

3
はい、それはオプションですが、キャッチはJavaで非常に高価な操作であることを忘れないでください
panser

2
それはもう当てはまりません。例外処理のパフォーマンスはかなり良好です。Java Regexはかなり遅いことを忘れないでください。つまり:本当に遅い!実際には、文字列を上記の正規表現に一致させる代わりに、Base64をデコードして、機能していないことを確認する方が高速です。私は大まかなテストを行いましたが、Java Regexマッチングは、デコードで最終的な例外をキャッチするよりも約6倍遅くなります(!!)。
SvenDöring

テストの実行回数が増えると、実際には11倍遅くなります。Javaでのより良いRegex実装の時間です。JavaのNashorn JavaScriptエンジンを使用した正規表現チェックでさえ、はるかに高速です。信じられない。さらに、JavaScript正規表現(Nashornを使用)は、はるかに強力です。
SvenDöring19年

3
Java 8ではなくJava 11を使用すると、正規表現チェックはさらに22倍遅くなります。🤦(Base64でデコードが速くなったので。)
スヴェンDöring

15

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

これを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
これは何語?言語に言及せずに質問
Ozkan '27

これは機能しません。ドキュメントを読むReturns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley

1
どうやって?入力に外側の文字が含まれている場合、それはbase64ではありませんよね?
Suneel Kumar 2017

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

確認したIFの文字列の長さが4 Aftwerwardsの倍数であることを確認するために、この正規表現を使用するすべての文字列では、base64でエンコードされた文字です。

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

使用するライブラリが改行を追加して、1行あたり最大76文字のルールを遵守する場合は、それらを空の文字列に置き換えます。


上記のリンクは404を示しています。確認して更新してください。
Ankur 14

@AnkurKumarは申し訳ありませんが、人々がクールでないURLを持っている場合に起こります。どこに移動したのかわかりません。Googleを通じて他の役立つリソースを見つけてください
Yaw Boakye 2014

古いページはいつでもweb.archive.orgから取得できます-これが元のURLです。web.archive.org/web/20120919035911/http://…または、ここにテキストを投稿しました:gist.github.com/mika76/d09e2b65159e435e7a4cc5b0299c3e84
Mladen Mihajlovic

4

Base64には多くのバリアントがあるので、文字列処理したいバリアントに似ているかどうかを判断することを検討してください。そのように、あなたはインデックスとパディング文字に関して、以下の正規表現を調整する必要があります(つまり+/=)。

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

使用法:

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

3

これを試して:

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

文字列がbase64でエンコードされているかどうかを確認することはできません。その文字列がbase64エンコードされた文字列形式であるかどうかを検証することのみが可能です。つまり、それはbase64エンコードによって生成された文字列である可能性があります(文字列が正規表現に対して検証されるか、ライブラリを使用できるかどうかを確認するには、多くの場合、この質問に対する他の回答は、これをチェックするための良い方法を提供するため、詳細には触れません。

たとえば、string flowは、base64でエンコードされた有効な文字列です。しかし、それが単なる文字列なのflowか、英語の単語なのか、それともBase 64でエンコードされた文字列なのかを知ることは不可能です。~Z0


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

この正規表現は、レール内のアプリケーションでbase64を識別するのに役立ちました。問題は1つだけでした。それは、文字列「errorDescripcion」を認識し、エラーを生成して、文字列の長さを検証するだけで解決することです。


上記の正規表現/^.....$/.match(my_string)は、「一致しない終了)」と言ってフォーマットエラーを発生させます
james2611nov

そして、 '文字クラスの早期終了:/ ^(([A-ZA-Z0-9 + /'を持つ。構文エラー
james2611nov

Nevermindは、すべての/文字の前に\を追加して修正しました。
james2611nov 2018年

errorDescription有効なbase64文字列であり、バイナリシーケンスのバイト(16進数)にデコードします7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27
Luis Colorado

base64でエンコードされた文字列をチェックするのに最適です。
Deepak Lakhara

1

これは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.")

概要: Base64エンコードされている場合はtrueをIsBase64("string here")返し、Base64エンコードされていない場合はfalseを返します。string herestring here


1

C# これは素晴らしいパフォーマンスです:

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
ラングドン

2
問題を解決するためにプログラミング言語を切り替えることをお勧めすることは、一般に有効な応答ではありません。
Luis Colorado

0

システム内の文字列に特定の制限または識別があることを除いて、文字列とbase64エンコードを区別する方法はありません。


0

このスニペットは、元のコンテンツ(チェックサムなど)の長さがわかっている場合に役立ちます。エンコードされたフォームが正しい長さであることを確認します。

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

RegExが機能せず、元の文字列の形式スタイルがわかっている場合は、この形式を再表現することにより、ロジックを逆にすることができます。

たとえば、base64でエンコードされたxmlファイルを操作し、ファイルに有効なxmlマークアップが含まれているかどうかを確認します。想定できない場合は、base64でデコードされていると考えます。これは動的ではありませんが、小さなアプリケーションでは問題なく機能します。


0

これは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

前述の正規表現を使用してこれを試してください:

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

...スペースがある場合、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");
 }

では、解決策を教えてください。
マルコ、

0

デコード時にASCII文字の文字列を取得した場合、その文字列はエンコードされていませんでした

(RoR)ルビ解:

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

私はこれを使おうとします、はい、これは機能しています

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

ただし、少なくとも文字の終わりが=であることを確認する条件を追加しました=

string.lastIndexOf("=") >= 0

確認する理由=Base64使用している仕様は何ですか?どういうend of the character意味ですか、そして非負はそれをどのようにlastIndexOf()チェックしますか?
greybeard
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.