如何检查字符串是否为Base64编码


194

我想解码Base64编码的字符串,然后将其存储在数据库中。如果输入不是Base64编码的,我需要抛出一个错误。

如何检查字符串是否为Base64编码?


为什么?情况如何发生?
罗恩侯爵

2
没有指定您要针对的编程语言(和/或)操作系统,这是一个非常开放的问题
bcarroll

5
您可以确定的是,该字符串仅包含对base64编码的字符串有效的字符。可能无法确定该字符串是某些数据的base64编码版本。例如,test1234是一个有效的base64编码的字符串,解码时会得到一些字节。没有独立于test1234base64编码的字符串的独立于应用程序的结论方法。
Kinjal Dixit '02

Answers:


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}==)$指的三种形式之一的串端部:[A-Za-z0-9+/]{4}[A-Za-z0-9+/]{3}=[A-Za-z0-9+/]{2}==


10
只是想验证一下,所以请为我的问题提供帮助:该正则表达式始终只引用base64字符串的保证是什么?如果有任何字符串没有空格并且是4个字符的倍数,那么该字符串将被视为base64字符串吗?
DShah 2012年

3
然后,它是可以解码的有效base64字符串。您可以添加最小长度约束;例如,而不是四个组的零个或多个重复,而需要(例如)四个或更多。这也取决于您的问题。(?夏威夷)如果您的用户经常与长词和纯ASCII语言输入一个字它更容易出错相比,非base64输入流通常包含空格,标点符号等
tripleee

62
这仅表明输入可能是 b64编码的值,但是并没有说明输入是否实际上是b64编码的值。换句话说,abcd将匹配,但不一定代表普通abcd输入的编码值
Tzury Bar Yochay

3
您的regexp不正确,因为它不匹配空字符串,根据RFC 4648,它是零长度二进制数据的base64编码。–
reddish

5
@Adomas,"pass" 是完全有效的BASE64字符串,解码为字节序列0xa50xab0x2c。如果您没有更多的上下文来决定,为什么要先验地放弃它?
路易斯·科罗拉多

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 2013年

7
您也可以使用Base64.isBase64(String base64)来代替自己将其转换为字节数组。
Sasa 2014年

5
可悲的是,基于文档:commons.apache.org/proper/commons-codec/apidocs/org/apache/…:“测试给定的字符串以查看它是否仅包含Base64字母内的有效字符。目前,该方法将空格视为有效。” 这意味着该方法具有一些误报,例如“空白”或数字(“ 0”,“ 1”)。
Christian Vielma

字符串Base64.isBase64(content)
ema

3
这个答案是错误的,因为即使它不是Base64编码的值,也给定stringToBeChecked="some plain text"它会设置boolean isBase64=true。阅读commons-codec-1.4的源代码,Base64.isArrayByteBase64()它仅检查字符串中的每个字符对于Base64编码均有效,并允许空白。
布拉德(Brad)

49

好吧,您可以:

  • 检查长度是否为4个字符的倍数
  • 检查每个字符是否都位于集合AZ,az,0-9,+,/中,但末尾的填充为0、1或2个'='字符

如果您期望它将是base64,那么您可以使用平台上可用的任何库尝试将其解码为字节数组,如果它不是有效的base 64则抛出异常。这取决于您的平台,当然。


解析与验证的不同之处至少在于,它需要用于解码字节数组的内存。因此,在某些情况下,这不是最有效的方法。
Victor Yarema,

1
@VictorYarema:我建议使用仅验证方法(项目符号)和解析方法(项目符号之后)。
乔恩·斯基特

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中catch是相当昂贵的操作
panser

2
事实不再如此。异常处理执行得很好。您最好不要忘记Java Regex相当慢。我的意思是:真的很慢!实际上,解码Base64并检查其是否正常工作(而不是将String与上述Regex匹配)是更快的。我做了一个粗略的测试,Java Regex匹配的速度比捕获解码时的异常要慢六倍(!!)。
SvenDöring19年

通过更多的测试运行,实际上速度要慢11倍。现在是时候用Java更好地实现Regex了。甚至使用Java中的Nashorn JavaScript引擎进行的Regex检查都快得多。难以置信的。此外,JavaScript Regex(与Nashorn一起使用)功能更强大。
SvenDöring19年

3
使用Java 11(而不是Java 8),Regex检查的速度甚至慢22倍。🤦(因为Base64解码的速度更快。)
SvenDöring19年

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
这是哪一种语言?有人问,而无需引用语言
厄兹坎

这是行不通的。阅读文档Returns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley

1
怎么样?如果输入包含外部字符,那么它不是base64,对吗?
Suneel Kumar '02

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

如果您使用的库添加了一个换行符,以观察每行最多76个字符,请用空字符串替换它们。


提到的链接显示404。请检查并更新。
Ankur 2014年

抱歉@AnkurKumar,但是当人们使用不正确的URL时,就会发生这种情况:他们一直在变化。我不知道它搬到哪里了。希望您能通过Google找到其他有用的资源
Yaw Boakye 2014年

您总是可以从web.archive.org获取旧页面-这是原始网址。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编码生成的字符串(要检查是否可以针对正则表达式验证字符串或可以使用库,很多该问题的其他答案提供了检查此问题的好方法,因此我将不赘述。

例如,字符串flow是有效的base64编码的字符串。但是不可能知道它只是一个简单的字符串,一个英语单词flow还是以64位编码的字符串~Z0


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

这个正则表达式帮助我在Rails的应用程序中识别了base64,我只有一个问题,那就是它识别字符串“ errorDescripcion”,我生成一个错误,要解决这个问题,只需验证字符串的长度即可。


上面的正则表达式/^.....$/.match(my_string)通过说'Unmatched close)给出格式错误
-james2611nov

并带有'char-class的提早结束:/ ^(([[A-Za-z0-9 + /']语法错误
。– james2611nov

没关系,可以通过在每个/字符前添加\来解决此问题。
james2611nov

errorDescription是有效的base64字符串时,它解码成字节二进制序列(十六进制): 7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27
路易斯·科罗拉多

它对检查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.")

摘要: IsBase64("string here")返回,如果string here是Base64编码,并返回,如果string here不是Base64编码。


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
建议切换编程语言来解决问题,通常是无效的响应。
路易斯·科罗拉多

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()?非负数如何检查呢?
灰胡子
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.