วิธีตรวจสอบสตริงที่เข้ารหัส Base64 ที่ถูกต้อง


127

มีวิธีใน C # เพื่อดูว่าสตริงที่เข้ารหัส Base 64 นอกเหนือจากการพยายามแปลงและดูว่ามีข้อผิดพลาดหรือไม่? ฉันมีรหัสโค้ดดังนี้:

// Convert base64-encoded hash value into a byte array.
byte[] HashBytes = Convert.FromBase64String(Value);

ฉันต้องการหลีกเลี่ยงข้อยกเว้น "อักขระไม่ถูกต้องในสตริงฐาน 64" ที่เกิดขึ้นหากค่าไม่ใช่สตริง 64 ฐานที่ถูกต้อง ฉันต้องการตรวจสอบและส่งคืนเท็จแทนการจัดการข้อยกเว้นเพราะฉันคาดว่าบางครั้งค่านี้จะไม่เป็นสตริง 64 ฐาน มีวิธีตรวจสอบก่อนใช้ฟังก์ชัน Convert.FromBase64String หรือไม่?

ขอบคุณ!

อัปเดต:
ขอบคุณสำหรับคำตอบทั้งหมดของคุณ นี่คือวิธีการขยายที่คุณสามารถใช้ได้จนถึงตอนนี้ดูเหมือนว่าสตริงของคุณจะผ่าน Convert.FromBase64String โดยไม่มีข้อยกเว้น .NET ดูเหมือนจะละเว้นช่องว่างต่อท้ายและสิ้นสุดทั้งหมดเมื่อแปลงเป็น 64 ฐานดังนั้น "1234" จึงถูกต้องและเป็น "1234"

public static bool IsBase64String(this string s)
{
    s = s.Trim();
    return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);

}

สำหรับผู้ที่สงสัยเกี่ยวกับประสิทธิภาพของการทดสอบเทียบกับการจับและข้อยกเว้นในกรณีส่วนใหญ่สำหรับสิ่งพื้นฐาน 64 นี้จะตรวจสอบได้เร็วกว่าที่จะจับข้อยกเว้นจนกว่าคุณจะถึงระยะเวลาที่กำหนด ยิ่งเล็กความยาวเร็วเท่าไหร่

ในการทดสอบที่ไม่เป็นไปตามหลักวิทยาศาสตร์ของฉัน: สำหรับการทำซ้ำ 10,000 ครั้งสำหรับความยาวอักขระ 100,000 - 110000 การทดสอบก่อนนั้นเร็วกว่า 2.7 เท่า

สำหรับการทำซ้ำ 1,000 ครั้งสำหรับความยาวอักขระ 1-16 อักขระสำหรับการทดสอบทั้งหมด 16,000 ครั้งจะเร็วขึ้น 10.9 เท่า

ฉันแน่ใจว่ามีจุดที่ดีกว่าในการทดสอบด้วยวิธีการตามข้อยกเว้น ฉันไม่รู้ว่าจุดนั้นคืออะไร


1
ขึ้นอยู่กับว่าคุณต้องการให้เช็ค "ละเอียดถี่ถ้วน" เพียงใด คุณสามารถใช้การตรวจสอบความถูกต้องล่วงหน้าได้โดยใช้ regex ตามที่คนอื่น ๆ ตอบ แต่นั่นไม่ใช่ตัวบ่งชี้เดียว การเข้ารหัส base64 จำเป็นต้องมีช่องว่างภายในในบางกรณีโดยใช้=เครื่องหมาย หากช่องว่างภายในไม่ถูกต้องจะทำให้เกิดข้อผิดพลาดแม้ว่าอินพุตจะตรงกับนิพจน์ก็ตาม
vcsjones

1
เงื่อนไขของคุณไม่เป็นไปตามสตริง base64 เท่านั้น พิจารณาสตริง\n\fLE16- วิธีของคุณจะให้ผลบวกเท็จสำหรับสิ่งนี้ สำหรับใครที่อ่านและกำลังมองหาวิธีที่เข้าใจผิด ฉันจะแนะนำจับ FormatException หรือใช้ข้อมูลจำเพาะเหมาะ RegEx ดูstackoverflow.com/questions/475074/...
โมฆะ

หากวิธีการข้างต้นส่งกลับเท็จฉันจะเพิ่มความยาวที่ถูกต้องได้อย่างไร
Paul Alexander

3
ฉันเชื่อว่า RegEx ควรจะเป็น@"^[a-zA-Z0-9\+/]*={0,2}$"
azatar

โซลูชันนี้ไม่น่าเชื่อถือ จะล้มเหลวหากคุณเพิ่มสตริงอักขระเดียวกัน 4 ตัว
Bettimms

คำตอบ:


49

มันค่อนข้างง่ายที่จะจดจำสตริง Base64 เนื่องจากจะประกอบด้วยอักขระเท่านั้น'A'..'Z', 'a'..'z', '0'..'9', '+', '/'และมักจะถูกเติมที่ท้ายด้วย '=' ไม่เกินสามตัวเพื่อทำให้ความยาวเป็นทวีคูณของ 4 แต่แทนที่จะเปรียบเทียบสิ่งเหล่านี้คุณจะ ' d ควรละเว้นข้อยกเว้นจะดีกว่าหากเกิดขึ้น


1
ฉันคิดว่าคุณมาถูกทางแล้ว ฉันทำการทดสอบบางอย่างและดูเหมือนว่าจะเป็นทวีคูณของ 4 แทนที่จะเป็น 3
Chris Mullins

1
ความยาวต้องเป็นผลคูณของ 3 ในขณะเข้ารหัสเพื่อให้การเข้ารหัสสำเร็จ! ขออภัยด้วย ... และใช่คุณพูดถูก ... สตริงที่เข้ารหัสมีความยาวซึ่งเป็นผลคูณของ 4 นั่นคือเหตุผลที่เราใส่ไม่เกิน 3 '='
Anirudh Ramanathan

4
ทำเครื่องหมายว่าถูกต้องเนื่องจากคุณเป็นคนแรกที่พูดถึงหลายสิ่ง ฉันอัปเดตคำถามของฉันด้วยการใช้งานโซลูชันโปรดแจ้งให้เราทราบหากคุณพบปัญหาใด ๆ
Chris Mullins

48

ใช้ Convert.TryFromBase64String จาก C # 7.2

public static bool IsBase64String(string base64)
{
   Span<byte> buffer = new Span<byte>(new byte[base64.Length]);
   return Convert.TryFromBase64String(base64, buffer , out int bytesParsed);
}

1
ฉันไม่รู้ว่านั่นเป็นเรื่อง ฉันคิดว่านี่น่าจะเป็นคำตอบใหม่ถ้าใช้ c # 7.2
Chris Mullins

4
ใช้งานได้เฉพาะใน. NET Core 2.1+ หรือ. NET Standard 2.1+
Cyrus

C # เป็นคอมไพเลอร์และ TryFromBase64String เป็น API ของ. NET framework :)
user960567

Convert.TryFromBase64String(base64.PadRight(base64.Length / 4 * 4 + (base64.Length % 4 == 0 ? 0 : 4), '='), new Span<byte>(new byte[base64.Length]), out _)นี้จะกลับเท็จสำหรับสตริงที่ไม่ใช่เบาะนี่คือการแก้ไข: ขอบคุณ.
rvnlord

44

ฉันรู้ว่าคุณบอกว่าคุณไม่ต้องการจับข้อยกเว้น แต่เนื่องจากการจับข้อยกเว้นมีความน่าเชื่อถือมากกว่าฉันจะโพสต์คำตอบนี้ต่อไป

public static bool IsBase64(this string base64String) {
     // Credit: oybek https://stackoverflow.com/users/794764/oybek
     if (string.IsNullOrEmpty(base64String) || base64String.Length % 4 != 0
        || base64String.Contains(" ") || base64String.Contains("\t") || base64String.Contains("\r") || base64String.Contains("\n"))
        return false;

     try{
         Convert.FromBase64String(base64String);
         return true;
     }
     catch(Exception exception){
     // Handle the exception
     }
     return false;
}

อัปเดต:ฉันได้อัปเดตเงื่อนไขขอบคุณoybekเพื่อปรับปรุงความน่าเชื่อถือเพิ่มเติม


1
การโทรbase64String.Containsหลายครั้งอาจทำให้เกิดประสิทธิภาพต่ำในกรณีbase64Stringที่เป็นสตริงขนาดใหญ่
NucS

@NucS คุณพูดถูกเราสามารถใช้ regex ที่รวบรวมได้ที่นี่
harsimranb

1
คุณสามารถตรวจสอบbase64String== null || base64String.Length == 0กับstring.IsNullOrEmpty(base64String)
Daniël Tulp

โปรดทราบว่า Base64 สามารถมีช่องว่าง (เช่นตัวแบ่งบรรทัด) ได้โดยไม่มีปัญหา พวกเขาจะไม่สนใจโดยตัวแยกวิเคราะห์
Timothy

2
เนื่องจากเราสามารถเข้าถึงซอร์สโค้ด. NET ได้แล้วเราจึงเห็นฟังก์ชัน FromBase64String () ทำการตรวจสอบทั้งหมดนี้ referencesource.microsoft.com/#mscorlib/system/…หากเป็นสตริง base64 ที่ถูกต้องคุณจะตรวจสอบสองครั้ง บางทีอาจเป็นไปได้ที่จะลอง / จับข้อยกเว้น
iheartcsharp

16

ฉันเชื่อว่า regex ควรเป็น:

    Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,2}$")

จับคู่เพียงหนึ่งหรือสองเครื่องหมายต่อท้าย '=' ไม่ใช่สาม

sควรเป็นสตริงที่จะตรวจสอบ Regexเป็นส่วนหนึ่งของSystem.Text.RegularExpressionsเนมสเปซ


2
ไม่ได้ตรวจสอบ
ว่าความ

7

ทำไมไม่จับข้อยกเว้นและส่งคืน False?

วิธีนี้หลีกเลี่ยงค่าใช้จ่ายเพิ่มเติมในกรณีทั่วไป


1
นี่เป็นกรณีที่ผิดปกติฉันเดาว่าฉันจะใช้ค่าที่ไหนมีแนวโน้มที่จะไม่ใช่ฐาน 64 ดังนั้นฉันจึงควรหลีกเลี่ยงค่าเหนือศีรษะของข้อยกเว้น ตรวจสอบก่อนจะเร็วกว่ามาก ฉันกำลังพยายามแปลงระบบเก่าที่ฉันได้รับมาจากรหัสผ่านที่ชัดเจนเป็นค่าที่แฮช
Chris Mullins

2
นิพจน์ทั่วไปไม่เคยเร็วไปกว่าที่ไทเลอร์แนะนำ
Vincent Koeman

ดูความคิดเห็นที่ด้านล่างของโพสต์ของฉัน ฉันคิดว่าขึ้นอยู่กับความยาวของสตริงที่คุณกำลังใช้งานการทดสอบก่อนโดยเฉพาะอย่างยิ่งสำหรับสตริงขนาดเล็กเช่นรหัสผ่านที่แฮช สตริงต้องเป็นผลคูณของ 4 ถึงจะถึง regex ได้จากนั้น regex บนสตริงขนาดเล็กจะเร็วกว่าสตริงขนาดใหญ่มาก
Chris Mullins

2
ในโลกที่สมบูรณ์แบบเราไม่ควรเขียนโค้ดที่มีการออกแบบตรรกะทางธุรกิจหรือเป็นที่รู้กันว่าโยนข้อยกเว้น ข้อยกเว้น try / catch block มีราคาแพงเกินไปที่จะใช้เป็นบล็อคการตัดสินใจ
Ismail Hawayel

7

เพื่อความสมบูรณ์ฉันต้องการให้มีการใช้งานบางอย่าง โดยทั่วไปแล้ว Regex เป็นวิธีการที่มีราคาแพงโดยเฉพาะอย่างยิ่งหากสตริงมีขนาดใหญ่ (ซึ่งเกิดขึ้นเมื่อถ่ายโอนไฟล์ขนาดใหญ่) แนวทางต่อไปนี้พยายามตรวจจับวิธีที่เร็วที่สุดก่อน

public static class HelperExtensions {
    // Characters that are used in base64 strings.
    private static Char[] Base64Chars = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
    /// <summary>
    /// Extension method to test whether the value is a base64 string
    /// </summary>
    /// <param name="value">Value to test</param>
    /// <returns>Boolean value, true if the string is base64, otherwise false</returns>
    public static Boolean IsBase64String(this String value) {

        // The quickest test. If the value is null or is equal to 0 it is not base64
        // Base64 string's length is always divisible by four, i.e. 8, 16, 20 etc. 
        // If it is not you can return false. Quite effective
        // Further, if it meets the above criterias, then test for spaces.
        // If it contains spaces, it is not base64
        if (value == null || value.Length == 0 || value.Length % 4 != 0
            || value.Contains(' ') || value.Contains('\t') || value.Contains('\r') || value.Contains('\n'))
            return false;

        // 98% of all non base64 values are invalidated by this time.
        var index = value.Length - 1;

        // if there is padding step back
        if (value[index] == '=')
            index--;

        // if there are two padding chars step back a second time
        if (value[index] == '=')
            index--;

        // Now traverse over characters
        // You should note that I'm not creating any copy of the existing strings, 
        // assuming that they may be quite large
        for (var i = 0; i <= index; i++) 
            // If any of the character is not from the allowed list
            if (!Base64Chars.Contains(value[i]))
                // return false
                return false;

        // If we got here, then the value is a valid base64 string
        return true;
    }
}

แก้ไข

ตามที่Samแนะนำคุณสามารถเปลี่ยนซอร์สโค้ดได้เล็กน้อย เขาให้แนวทางที่มีประสิทธิภาพดีกว่าสำหรับขั้นตอนสุดท้ายของการทดสอบ กิจวัตร

    private static Boolean IsInvalid(char value) {
        var intValue = (Int32)value;

        // 1 - 9
        if (intValue >= 48 && intValue <= 57) 
            return false;

        // A - Z
        if (intValue >= 65 && intValue <= 90) 
            return false;

        // a - z
        if (intValue >= 97 && intValue <= 122) 
            return false;

        // + or /
        return intValue != 43 && intValue != 47;
    } 

สามารถใช้เพื่อแทนที่if (!Base64Chars.Contains(value[i]))บรรทัดด้วยif (IsInvalid(value[i]))

ซอร์สโค้ดที่สมบูรณ์พร้อมการปรับปรุงจากSamจะมีลักษณะดังนี้ (ลบความคิดเห็นเพื่อความชัดเจน)

public static class HelperExtensions {
    public static Boolean IsBase64String(this String value) {
        if (value == null || value.Length == 0 || value.Length % 4 != 0
            || value.Contains(' ') || value.Contains('\t') || value.Contains('\r') || value.Contains('\n'))
            return false;
        var index = value.Length - 1;
        if (value[index] == '=')
            index--;
        if (value[index] == '=')
            index--;
        for (var i = 0; i <= index; i++)
            if (IsInvalid(value[i]))
                return false;
        return true;
    }
    // Make it private as there is the name makes no sense for an outside caller
    private static Boolean IsInvalid(char value) {
        var intValue = (Int32)value;
        if (intValue >= 48 && intValue <= 57)
            return false;
        if (intValue >= 65 && intValue <= 90)
            return false;
        if (intValue >= 97 && intValue <= 122)
            return false;
        return intValue != 43 && intValue != 47;
    }
}

4

คำตอบต้องขึ้นอยู่กับการใช้งานของสตริง มีหลายสตริงที่อาจเป็น "base64 ที่ถูกต้อง" ตามไวยากรณ์ที่ผู้โพสต์หลายคนแนะนำ แต่นั่นอาจ "ถูกต้อง" ในการถอดรหัสเป็นขยะ ตัวอย่าง: สตริง 8char Portlandคือ Base64 ที่ถูกต้อง อะไรคือจุดที่ระบุว่านี่คือ Base64 ที่ถูกต้อง? ฉันเดาว่าในบางจุดคุณต้องการทราบว่าสตริงนี้ควรหรือไม่ควรถอดรหัส Base64

ในกรณีของฉันฉันมีสตริงการเชื่อมต่อ Oracle ที่อาจเป็นข้อความธรรมดาเช่น:

Data source=mydb/DBNAME;User Id=Roland;Password=.....`

หรือใน base64 เช่น

VXNlciBJZD1sa.....................................==

ฉันต้องตรวจสอบว่ามีอัฒภาคหรือไม่เพราะนั่นพิสูจน์ได้ว่าไม่ใช่ base64 ซึ่งแน่นอนว่าเร็วกว่าวิธีการใด ๆ ข้างต้น


เห็นด้วยเฉพาะกรณียังกำหนดให้มีการตรวจสอบอย่างรวดเร็วเพิ่มเติม เช่นเดียวกับสตริงการเชื่อมต่อข้อความธรรมดาเทียบกับการเข้ารหัส base64
Oybek

2

Knibb กฎฟุตบอลสูง!

สิ่งนี้ควรจะค่อนข้างเร็วและแม่นยำ แต่ฉันยอมรับว่าฉันไม่ได้ผ่านการทดสอบอย่างละเอียดเพียงเล็กน้อย

หลีกเลี่ยงข้อยกเว้นที่มีราคาแพง regex และหลีกเลี่ยงการวนซ้ำชุดอักขระแทนที่จะใช้ช่วง ascii สำหรับการตรวจสอบความถูกต้อง

public static bool IsBase64String(string s)
    {
        s = s.Trim();
        int mod4 = s.Length % 4;
        if(mod4!=0){
            return false;
        }
        int i=0;
        bool checkPadding = false;
        int paddingCount = 1;//only applies when the first is encountered.
        for(i=0;i<s.Length;i++){
            char c = s[i];
            if (checkPadding)
            {
                if (c != '=')
                {
                    return false;
                }
                paddingCount++;
                if (paddingCount > 3)
                {
                    return false;
                }
                continue;
            }
            if(c>='A' && c<='z' || c>='0' && c<='9'){
                continue;
            }
            switch(c){ 
              case '+':
              case '/':
                 continue;
              case '=': 
                 checkPadding = true;
                 continue;
            }
            return false;
        }
        //if here
        //, length was correct
        //, there were no invalid characters
        //, padding was correct
        return true;
    }

2
public static bool IsBase64String1(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            try
            {
                Convert.FromBase64String(value);
                if (value.EndsWith("="))
                {
                    value = value.Trim();
                    int mod4 = value.Length % 4;
                    if (mod4 != 0)
                    {
                        return false;
                    }
                    return true;
                }
                else
                {

                    return false;
                }
            }
            catch (FormatException)
            {
                return false;
            }
        }

ทำไมคุณถึงพยายามแปลงก่อนแล้วจึงควบคุมสิ่งอื่น ๆ
Snr

@Snr คุณพูดถูก ฉันคิดว่านี่คือสิ่งที่เขาต้องเปลี่ยน: if (value.EndsWith ("=")) {value = value.Trim (); int mod4 = ค่าความยาว% 4; ถ้า (mod4! = 0) {กลับเท็จ; } Convert.FromBase64String (ค่า); กลับจริง } else {กลับเท็จ; }
Wajid khan

2

ฉันจะใช้แบบนี้เพื่อที่ฉันจะได้ไม่ต้องเรียกวิธีการแปลงอีกครั้ง

   public static bool IsBase64(this string base64String,out byte[] bytes)
    {
        bytes = null;
        // Credit: oybek http://stackoverflow.com/users/794764/oybek
        if (string.IsNullOrEmpty(base64String) || base64String.Length % 4 != 0
           || base64String.Contains(" ") || base64String.Contains("\t") || base64String.Contains("\r") || base64String.Contains("\n"))
            return false;

        try
        {
             bytes=Convert.FromBase64String(base64String);
            return true;
        }
        catch (Exception)
        {
            // Handle the exception
        }

        return false;
    }

2

ทำการถอดรหัสเข้ารหัสใหม่และเปรียบเทียบผลลัพธ์กับสตริงเดิม

public static Boolean IsBase64(this String str)
{
    if ((str.Length % 4) != 0)
    {
        return false;
    }

    //decode - encode and compare
    try
    {
        string decoded = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(str));
        string encoded = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(decoded));
        if (str.Equals(encoded, StringComparison.InvariantCultureIgnoreCase))
        {
            return true;
        }
    }
    catch { }
    return false;
}

1

อิมโฮนี่ไม่ไหวจริงๆ โซลูชันที่โพสต์ทั้งหมดล้มเหลวสำหรับสตริงเช่น"test"เป็นต้น หากแบ่งได้ถึง 4 ไม่เป็นโมฆะหรือว่างเปล่าและหากเป็นอักขระ base64 ที่ถูกต้องก็จะผ่านการทดสอบทั้งหมด ที่เป็นได้หลายสาย ...

ดังนั้นไม่มีการแก้ปัญหาอื่น ๆ จริงกว่ารู้ว่านี้เป็นฐาน 64 เข้ารหัสสตริง สิ่งที่ฉันคิดขึ้นมาคือ:

if (base64DecodedString.StartsWith("<xml>")
{
    // This was really a base64 encoded string I was expecting. Yippie!
}
else
{
    // This is gibberish.
}

ฉันคาดว่าสตริงที่ถอดรหัสจะเริ่มต้นด้วยโครงสร้างบางอย่างดังนั้นฉันจึงตรวจสอบว่า


0

แน่ใจ เพียงให้แน่ใจว่าตัวละครแต่ละตัวอยู่ภายในa-z, A-Z, 0-9, /หรือและสตริงปลายด้วย+ ==(อย่างน้อยนั่นคือการใช้งาน Base64 ที่พบบ่อยที่สุดคุณอาจพบการใช้งานบางอย่างที่ใช้อักขระต่างจาก/หรือ+สำหรับอักขระสองตัวสุดท้าย)


ถ้าฉันเข้าใจอักขระสิ้นสุดจะขึ้นอยู่กับความยาวสุดท้ายของข้อความที่เข้ารหัส ดังนั้นหากข้อความที่เข้ารหัสไม่ใช่ความยาว% 4 ระบบจะรวม '='
Rafael Diego Nicoletti

0

ใช่เนื่องจากBase64เข้ารหัสข้อมูลไบนารีเป็นสตริง ASCII โดยใช้ชุดอักขระที่ จำกัด คุณสามารถตรวจสอบได้ด้วยนิพจน์ทั่วไปนี้:

/ ^ [A-Za-Z0-9 \ = \ + \ / \ s \ n] + $ / s

ซึ่งจะทำให้มั่นใจได้ว่าสตริงจะมีเฉพาะ AZ, az, 0-9, '+', '/', '=' และช่องว่างเท่านั้น


นั่นไม่ใช่วิธีที่แน่นอนที่จะบอกได้ Base64 เพิ่มช่องว่างให้คุณโดยใช้=อักขระในตอนท้าย หากช่องว่างภายในนั้นไม่ถูกต้องแสดงว่าไม่ใช่การเข้ารหัส base64 ที่ถูกต้องแม้ว่าจะตรงกับ regex ของคุณก็ตาม คุณสามารถสาธิตสิ่งนี้ได้โดยค้นหาสตริง 64 ฐานที่มี 1 หรือ 2 =ต่อท้ายลบออกและพยายามถอดรหัส
vcsjones

ฉันเชื่อว่า OP ขอให้ดักจับตัวละครที่ผิดกฎหมายไม่ใช่ว่า str ถูกกฎหมาย Base64 หากเป็นอย่างหลังแสดงว่าคุณถูกต้องแม้ว่าข้อผิดพลาดในการเติมใน Base64 จะง่ายกว่าในการดักจับโดยใช้ข้อยกเว้น
Rob Raisch

ไม่เป็นความจริงอย่างน้อยตัวแยกวิเคราะห์ base64 เวอร์ชัน. Net จะละเว้นช่องว่างภายในอย่างสมบูรณ์
Jay

0

ฉันขอแนะนำให้สร้างนิพจน์ทั่วไปเพื่อทำงาน คุณจะต้องตรวจสอบสิ่งนี้: [a-zA-Z0-9 + / =] คุณจะต้องตรวจสอบความยาวของสตริงด้วย ฉันไม่แน่ใจเกี่ยวกับเรื่องนี้ แต่ฉันค่อนข้างแน่ใจว่าถ้ามีบางอย่างถูกตัดออก (นอกเหนือจากช่องว่างภายใน "=") มันจะระเบิด

หรือดีกว่าลองดูคำถาม stackoverflow นี้


0

ฉันเพิ่งมีข้อกำหนดที่คล้ายกันมากโดยที่ฉันให้ผู้ใช้ทำการปรับแต่งรูปภาพใน<canvas>องค์ประกอบจากนั้นส่งรูปภาพผลลัพธ์ที่ดึง.toDataURL()ไปยังแบ็กเอนด์ ฉันต้องการทำการตรวจสอบความถูกต้องของเซิร์ฟเวอร์ก่อนที่จะบันทึกภาพและได้ติดตั้งValidationAttributeโดยใช้รหัสบางส่วนจากคำตอบอื่น ๆ :

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class Bae64PngImageAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null || string.IsNullOrWhiteSpace(value as string))
            return true; // not concerned with whether or not this field is required
        var base64string = (value as string).Trim();

        // we are expecting a URL type string
        if (!base64string.StartsWith("data:image/png;base64,"))
            return false;

        base64string = base64string.Substring("data:image/png;base64,".Length);

        // match length and regular expression
        if (base64string.Length % 4 != 0 || !Regex.IsMatch(base64string, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None))
            return false;

        // finally, try to convert it to a byte array and catch exceptions
        try
        {
            byte[] converted = Convert.FromBase64String(base64string);
            return true;
        }
        catch(Exception)
        {
            return false;
        }
    }
}

ที่คุณสามารถดูฉันกำลังคาดหวังว่า image / png สตริงประเภทซึ่งเป็นค่าเริ่มต้นที่ส่งกลับโดยเมื่อใช้<canvas>.toDataURL()


0

ตรวจสอบ Base64 หรือสตริงปกติ

บูลสาธารณะ IsBase64Encoded (String str)

{

try

{
    // If no exception is caught, then it is possibly a base64 encoded string
    byte[] data = Convert.FromBase64String(str);
    // The part that checks if the string was properly padded to the
    // correct length was borrowed from d@anish's solution
    return (str.Replace(" ","").Length % 4 == 0);
}
catch
{
    // If exception is caught, then it is not a base64 encoded string
   return false;
}

}


0

คำตอบทั้งหมดถูกย่อยออกเป็น 1 ฟังก์ชันที่ทำให้มั่นใจได้ 100% ว่าผลลัพธ์จะถูกต้อง


1) ใช้ฟังก์ชันดังต่อไปนี้:

    string encoded = "WW91ckJhc2U2NHN0cmluZw==";
    msgbox("Is string base64=" + IsBase64(encoded));

2) ด้านล่างคือฟังก์ชั่น:

  public bool IsBase64(string base64String)
    {
        try
        {
            if (!base64String.Length < 1)
            {
                if (!base64String.Equals(Convert.ToBase64String(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(Convert.FromBase64String(base64String)))), StringComparison.InvariantCultureIgnoreCase) & !System.Text.RegularExpressions.Regex.IsMatch(base64String, @"^[a-zA-Z0-9\+/]*={0,2}$"))
                {
                    return false;
                    return;
                }
                if ((base64String.Length % 4) != 0 || string.IsNullOrEmpty(base64String) || base64String.Length % 4 != 0 || base64String.Contains(" ") || base64String.Contains(Constants.vbTab) || base64String.Contains(Constants.vbCr) || base64String.Contains(Constants.vbLf))
                {
                    return false;
                    return;
                }
            }
            else
            {
                return false;
                return;
            }

            return true;
            return;
        }
        catch (FormatException ex)
        {
            return false;
            return;
        }
    }

-1

ฉันชอบแนวคิดของการตรวจสอบนิพจน์ทั่วไป นิพจน์ทั่วไปสามารถทำได้รวดเร็วและประหยัดค่าใช้จ่ายในการเข้ารหัสในบางครั้ง คำถามเดิมมีการอัปเดตที่ทำเพียงแค่นี้ ฉันพบว่าฉันไม่สามารถสันนิษฐานได้ว่าสตริงจะไม่เป็นโมฆะ ฉันจะขยายฟังก์ชันส่วนขยายเพื่อตรวจสอบสตริงต้นทางสำหรับ null หรือเว้นวรรคเฉพาะอักขระ

    public static bool IsBase64String(this string s)
    {
        if (string.IsNullOrWhiteSpace(s))
            return false;

        s = s.Trim();
        return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);

    }

สิ่งนี้ล้มเหลว พยายามส่งสตริงที่มี 4 อักขระเหมือนกันเช่น 'aaaa'
Bettimms
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.