在我开始之前:是的,我已经在这里和其他地方检查过这个主题的其他问题和答案。
我找到了一个示例字符串,.Net将对其进行base64解码,即使它实际上并不是base64编码的。这是一个例子:
Rhinocort水性64mcg /剂量喷鼻剂
.Net方法Convert.FromBase64String在解码此字符串时不会抛出异常,因此我的IsBase64Encoded方法很乐意为此字符串返回true。
有趣的是,如果我使用此字符串作为输入使用cygwin base64 -d命令,它将失败并显示消息无效输入。
更有趣的是,我认为属于这个可执行文件的源(http://libb64.sourceforge.net/)“解码”这个相同的字符串,其结果与我从.Net Convert.FromBase64String获得的结果相同。我会继续寻找其他地方的线索,但现在我很难过。
有什么想法吗?
答案 0 :(得分:1)
还有一个更好的解决方案,它还会检查输入字符串的长度。
我建议您在开始时进行检查。如果输入为null或为空,则返回false
。
http://www.codeproject.com/Questions/177808/How-to-determine-if-a-string-is-Base-decoded-or
答案 1 :(得分:0)
当字符串确实通过 Base64 解码并且解码后的数据具有特殊字符时,也许我们可以断定它不是有效的 Base64(这取决于编码)。此外,有时我们期望传递的数据是 Base64,但有时它可能没有正确填充“=”。因此,一种方法对 Base64 使用“严格”规则,另一种方法是“宽容”。
[TestMethod]
public void CheckForBase64()
{
Assert.IsFalse(IsBase64DataStrict("eyJhIjoiMSIsImIiOiI2N2NiZjA5MC00ZGRiLTQ3OTktOTlmZi1hMjhhYmUyNzQwYjEiLCJmIjoiMSIsImciOiIxIn0"));
Assert.IsTrue(IsBase64DataForgiving("eyJhIjoiMSIsImIiOiI2N2NiZjA5MC00ZGRiLTQ3OTktOTlmZi1hMjhhYmUyNzQwYjEiLCJmIjoiMSIsImciOiIxIn0"));
Assert.IsFalse(IsBase64DataForgiving("testing123"));
Assert.IsFalse(IsBase64DataStrict("ABBA"));
Assert.IsFalse(IsBase64DataForgiving("6AC648C9-C08F-4F9D-A0A5-3904CF15ED3E"));
}
public bool IsBase64DataStrict(string data)
{
if (string.IsNullOrWhiteSpace(data)) return false;
if ((new Regex(@"[^A-Z0-9+\/=]", RegexOptions.IgnoreCase)).IsMatch(data)) return false;
if (data.Length % 4 != 0) return false;
var e = data.IndexOf('=');
var l = data.Length;
if (!(e == -1 || e == l - 1 || (e == l - 2 && data[l - 1] == '='))) return false;
var decoded = string.Empty;
try
{
byte[] decodedData = Convert.FromBase64String(data);
decoded = Encoding.UTF8.GetString(decodedData);
}
catch(Exception)
{
return false;
}
//check for special chars that you know should not be there
char current;
for (int i = 0; i < decoded.Length; i++)
{
current = decoded[i];
if (current == 65533) return false;
if (!((current == 0x9 || current == 0xA || current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF))))
{
return false;
}
}
return true;
}
public bool IsBase64DataForgiving(string data)
{
if (string.IsNullOrWhiteSpace(data)) return false;
//it could be made more forgiving by replacing any spaces with '+' here
if ((new Regex(@"[^A-Z0-9+\/=]", RegexOptions.IgnoreCase)).IsMatch(data)) return false;
//this is the forgiving part
if (data.Length % 4 > 0)
data = data.PadRight(data.Length + 4 - data.Length % 4, '=');
var e = data.IndexOf('=');
var l = data.Length;
if (!(e == -1 || e == l - 1 || (e == l - 2 && data[l - 1] == '='))) return false;
var decoded = string.Empty;
try
{
byte[] decodedData = Convert.FromBase64String(data);
decoded = Encoding.UTF8.GetString(decodedData);
}
catch (Exception)
{
return false;
}
//check for special chars that you know should not be there
char current;
for (int i = 0; i < decoded.Length; i++)
{
current = decoded[i];
if (current == 65533) return false;
if (!((current == 0x9 || current == 0xA || current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF))))
{
return false;
}
}
return true;
}