ฉันสามารถใช้การเข้ารหัสชนิดใดเพื่อทำให้สตริงสั้นลงได้


13

ฉันสนใจในการเข้ารหัสสตริงที่ฉันมีและฉันอยากรู้ว่ามีการเข้ารหัสประเภทใดบ้างที่สามารถใช้ได้ซึ่งจะรวมเฉพาะอักขระอัลฟ่าและตัวเลขและควรลดจำนวนอักขระที่ต้องใช้เพื่อเป็นตัวแทนสตริง

จนถึงตอนนี้ฉันได้ดูการใช้การเข้ารหัส Base64 เพื่อทำสิ่งนี้ แต่ดูเหมือนว่าจะทำให้สตริงของฉันยาวขึ้นและบางครั้งก็รวมถึง==สิ่งที่ฉันต้องการหลีกเลี่ยง ตัวอย่าง:

ชื่อทดสอบ | 120101

กลายเป็น

dGVzdCBuYW1lfDEyMDEwMQ ==

ซึ่งเพิ่มจาก 16 ถึง 24 อักขระและรวมถึงตัวอักษรและตัวเลขที่ไม่ใช่

ไม่มีใครรู้ว่าการเข้ารหัสชนิดอื่นที่ฉันสามารถใช้เพื่อให้บรรลุความต้องการของฉันได้หรือไม่? คะแนนโบนัสหากมันอยู่ภายในกรอบ. NET หรือมีห้องสมุดบุคคลที่สามที่จะทำการเข้ารหัส


1
ไม่สามารถใช้การบีบอัดที่สูญเสียน้อยลงเช่นการเข้ารหัส Huffman !! มันเหมาะสำหรับตำรา ... แต่เมื่อถึงตอนจบคุณควรรู้เกี่ยวกับการกลายพันธุ์นี้ที่คุณได้ทำเพื่อให้ได้ข้อความนั้นกลับมา

6
คุณกำลังอธิบายการบีบอัดไม่ใช่การเข้ารหัส
Andy Smith

@Andrew - ตกลงคำแนะนำใด ๆ
Abe Miessler

คำตอบ:


30

'=' or '==' สุดท้ายใน Base64 มีไว้เพื่อให้จำนวนอักขระเป็น 4 เท่าเท่านั้นคุณสามารถลบออกได้เนื่องจากคุณสามารถนำกลับมาใช้ใหม่ได้ในภายหลัง โปรดทราบว่า Base64 ถูกเรียกเช่นนั้นเนื่องจากใช้64อักขระที่ต่างกัน ตัวอักษรตัวพิมพ์ใหญ่ตัวอักษรตัวพิมพ์เล็กและตัวเลขคือ 62 ดังนั้น Base64 จึงใช้ '/' และ '+' ซึ่งอาจเหมาะสมหรือไม่เหมาะสมกับค่าของคุณ

โดยทั่วไปถ้าคุณต้องการเข้ารหัสลำดับของไบต์เป็นอักขระตัวอักษรและตัวเลขต้องมีการขยายความยาวบางแห่งเนื่องจากมี 256 ค่าที่เป็นไปได้สำหรับไบต์และตัวอักษรและตัวเลข 62 ตัวเท่านั้น มันเป็นบางครั้งเรียกว่าหลักรังนกพิราบ รูปแบบการเข้ารหัสจะต้องมีการขยายความยาวเฉลี่ยของบันทึกปัจจัย256 / บันทึก 62 = 1.344 (เฉลี่ยมากกว่าทุกลำดับไบต์); มิฉะนั้นก็หมายความว่านกพิราบบางตัวถูกทับอัดจนตายที่ไหนสักแห่งและคุณจะไม่ได้รับมันกลับคืนโดยไม่มีความเสียหาย (ซึ่งหมายความว่า: สองสายที่เข้ารหัสแตกต่างกันไปเหมือนกันดังนั้นการถอดรหัสไม่สามารถทำงานได้อย่างน่าเชื่อถือ)

ตอนนี้มันค่อนข้างเป็นไปได้ที่สตริงของคุณจะไม่ตรงกับ "ลำดับของไบต์สุ่มที่สม่ำเสมอ"; สตริงของคุณมีความหมายบางอย่างซึ่งหมายความว่าลำดับไบต์ที่เป็นไปได้มากที่สุดจะไม่เกิดขึ้นเนื่องจากไม่มีความหมาย บนพื้นฐานนั้นคุณสามารถกำหนดรูปแบบการเข้ารหัสซึ่งจะทำให้เกิดการขยายความยาวน้อยกว่า Base64 ทั่วไป (หรือ Base62 หากคุณต้องการใช้ตัวอักษรและตัวเลขที่เข้มงวด) นี่คือการบีบอัดข้อมูลแบบ lossless มันใช้งานได้กับโมเดลความน่าจะเป็นที่กำหนดไว้อย่างชัดเจนว่าอะไรที่สามารถปรากฏเป็นอินพุตได้

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


1
+1 คำอธิบายที่ยอดเยี่ยม ฉันไม่ทราบเกี่ยวกับการ=/ ==เกี่ยวข้องกับความยาวต้องมีหลาย 4 ฉันอาจจะสามารถแก้ไขปัญหานี้ได้ตามความต้องการ
Abe Miessler

ใจคุณนี่ถือว่าขาด pigeonholes Unicode มีตัวอักษรมากมาย เราต้องการความเข้าใจปัญหาที่แท้จริงให้ดีขึ้น
MSalters

@ คุณคำนวณค่าส่วนขยายความยาวเฉลี่ยโดยใช้ส่วนการบันทึกอย่างไร จากแผนภาพในen.wikipedia.org/wiki/Base64มันทำให้เข้าใจได้ง่ายว่าถ่านที่ไม่ได้เข้ารหัสแต่ละตัวใช้เวลา 4/3 ตัวอักษรใน Base64 เพื่อเป็นตัวแทน เพียงแค่สงสัยว่าคุณได้ข้อสรุปแบบเดียวกันกับคณิตศาสตร์อย่างไร ... ขอบคุณ :)
Jonathan Lin

คำถามที่ไม่ดีและงี่เง่าของฉัน log (256) = 8 bits, log (64) = 6 bits ดังนั้นอัตราส่วนคือ 8/6 = 4/3 = 1.333 สำหรับ Base64 ไชโย
Jonathan Lin

4

โดยทั่วไปการเข้ารหัสอักขระใหม่จะกระทำเมื่อระบบรับไม่สามารถประมวลผลได้ ตัวอย่างเช่น BASE64 แสดงข้อมูลโดยใช้ 6 บิต (2 6ดังนั้น 64) ของอักขระเพื่อแสดงลำดับข้อมูลที่ยาวขึ้น (บางครั้งที่ปรากฏ "==" ในตอนท้ายคือการเติมสำหรับการจัดตำแหน่ง) นี่เป็นเพราะไฟล์รูปภาพของคุณในอีเมลอาจมี 0xFE อยู่และเซิร์ฟเวอร์อีเมลของคุณจะไม่มีความสุขในการส่งสัญญาณนั้น (หรืออักขระอื่น ๆ ที่ไม่ใช่การพิมพ์แบบดั้งเดิม)

ไม่มีการเข้ารหัสที่ "ลดขนาด" การเข้ารหัสเป็นเพียงการแม็พของบิตกับอักขระที่แสดง ASCII เป็นชุดอักขระ 7 บิต (การเข้ารหัส) ที่มักถูกเก็บไว้ในพื้นที่ 8 บิต หากคุณ จำกัด ช่วงที่คุณยอมรับคุณสามารถกำจัดอักขระควบคุมได้เช่นกัน

การใช้วิธีการนี้หมายความว่าคุณต้องเขียนสิ่งต่าง ๆ ในระดับบิตและมันก็เล่นได้อย่างไม่น่าเชื่อด้วยความเร็วและคำแนะนำของเครื่องจักร ตัวอย่างเช่นนั้นคือสาเหตุที่ Unicode คือ UTF-8, UTF-16 และ UTF-32

หากคุณกำลังทำสิ่งนี้เพื่อความปลอดภัย (นั่นเป็นเหตุผลที่คุณโพสต์ไว้ใน Security.SE ใช่มั้ย) เพียงแค่กรองสิ่งต่าง ๆ และเก็บไว้ตามปกติ หากคุณกำลังทำสิ่งนี้เพื่อประหยัดพื้นที่พิจารณาว่ารหัสพิเศษทั้งหมดและเวลาเข้าถึงที่ช้าลง (เพราะรายการส่วนใหญ่จะข้ามขอบเขตที่อยู่) คุ้มค่ากับการประหยัดพื้นที่

โดยโดยต่อไปนี้เป็นตัวอย่างจากหลักสูตร CS ที่เราต้องแปลง ASCII จากที่เก็บข้อมูล 8 บิตเป็น 7 บิต:

    memset(dest,0x00,8);
    memcpy(dest, source, length);

    for (int i = 0; i < 8; i++) {
            if (dest[i] & 0x80) {
                    fprintf(stderr, "%s: %s\n", dest, "Illegal byte sequence");
                    exit(EILSEQ);
            }
    }

    dest[0] = 0x7F & dest[0] | 0x80 & dest[1] << 7;
    dest[1] = 0x3F & dest[1] >> 1 | 0xC0 & dest[2] << 6;
    dest[2] = 0x1F & dest[2] >> 2 | 0xE0 & dest[3] << 5;
    dest[3] = 0x0F & dest[3] >> 3 | 0xF0 & dest[4] << 4;
    dest[4] = 0x07 & dest[4] >> 4 | 0xF8 & dest[5] << 3;
    dest[5] = 0x03 & dest[5] >> 5 | 0xFC & dest[6] << 2;
    dest[6] = 0x01 & dest[6] >> 6 | 0xFE & dest[7] << 1;
    dest[7] = 0x00; //Clearing out

2

คุณสามารถบีบอัดข้อมูลด้วยเช่น gzip, bzip2 หรือ lzma จากนั้นเรียกใช้ผ่าน base64 เพื่อ จำกัด ชุดอักขระที่ใช้ สิ่งนี้มีประโยชน์เฉพาะกับสตริงที่มีขนาดใหญ่กว่าร้อยไบต์หรือมากกว่า


1

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


การบีบอัด LZ เปรียบเทียบกับ gzip หรือ bzip2 ที่กล่าวถึงในคำแนะนำ attir อย่างไร
NoChance

gzip สร้างขึ้นบน LZ และ Huffman Coding เพิ่มเติมเกี่ยวกับ LZ en.wikipedia.org/wiki/LZ77
A.Rashad
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.