Tôi có thể sử dụng loại mã hóa nào để làm cho chuỗi ngắn hơn?


13

Tôi quan tâm đến việc mã hóa một chuỗi tôi có và tôi tò mò liệu có một loại mã hóa nào có thể được sử dụng sẽ chỉ bao gồm các ký tự alpha và số và tốt nhất là rút ngắn số lượng ký tự cần thiết để thể hiện chuỗi.

Cho đến nay tôi đã xem xét việc sử dụng mã hóa Base64 để làm điều này nhưng nó dường như làm cho chuỗi của tôi dài hơn và đôi khi bao gồm cả ==những gì tôi muốn tránh. Thí dụ:

tên kiểm tra | 120101

trở thành

dGVzdCBuYW1lfDEyMDEwMQ ==

trong đó có từ 16 đến 24 ký tự và bao gồm cả chữ và số.

Có ai biết một loại mã hóa khác mà tôi có thể sử dụng sẽ đạt được yêu cầu của tôi không? Điểm thưởng nếu được tích hợp vào .NET framework hoặc tồn tại thư viện bên thứ ba sẽ thực hiện mã hóa.


1
không thể sử dụng nén ít mất như mã hóa Huffman !! Chúng rất phù hợp cho các văn bản ... nhưng sau đó, khi nhận được, bạn thực sự nên biết về đột biến này mà bạn đã thực hiện để lấy lại văn bản.

6
Bạn đang mô tả nén, không mã hóa
Andy Smith

@Andrew - Ok, có gợi ý nào không?
Abe Miessler

Câu trả lời:


30

Cuối cùng '=' hoặc '==' trong Base64 chỉ có để làm cho số lượng ký tự là bội số của 4. Bạn có thể xóa nó, vì bạn luôn có thể đặt lại nó sau này. Lưu ý rằng Base64 được gọi như vậy vì nó sử dụng 64 ký tự riêng biệt. Chữ in hoa, chữ thường và chữ số, đó là 62. Vì vậy, Base64 cũng sử dụng '/' và '+', có thể phù hợp hoặc không phù hợp với hóa đơn của bạn.

Trên cơ sở chung, nếu bạn muốn mã hóa các chuỗi byte tùy ý thành các ký tự chữ và số, thì nhất thiết phải có phần mở rộng độ dài ở đâu đó, bởi vì có 256 giá trị có thể cho một byte và chỉ có 62 ký tự chữ và số. Đôi khi nó được gọi là nguyên tắc pigeonhole . Một lược đồ mã hóa phải có phần mở rộng độ dài trung bình của một bản ghi yếu tố 256 / log 62 = 1.344 (trung bình trên tất cả các chuỗi byte); mặt khác, điều đó có nghĩa là một số chim bồ câu đang bị nghiền nát ở đâu đó và bạn sẽ không lấy lại được chúng mà không bị hư hại (có nghĩa là: hai chuỗi riêng biệt được mã hóa giống nhau, vì vậy việc giải mã không thể hoạt động một cách đáng tin cậy).

Bây giờ, hoàn toàn có khả năng các chuỗi của bạn không chính xác là "chuỗi các byte ngẫu nhiên đồng nhất"; chuỗi của bạn có một số ý nghĩa có nghĩa là hầu hết các chuỗi byte có thể sẽ không xảy ra, bởi vì chúng là vô nghĩa. Trên cơ sở đó, có lẽ bạn có thể nghĩ ra một sơ đồ mã hóa sẽ phát sinh phần mở rộng ít hơn so với Base64 (hoặc Base62 nếu bạn cần phải tuân theo các ký tự chữ và số nghiêm ngặt). Đây là nén dữ liệu lossless . Nó hoạt động trên một mô hình xác suất được xác định rõ ràng về những gì có thể xuất hiện dưới dạng đầu vào.

Tóm tắt: một sơ đồ chung để mã hóa các chuỗi thành các chuỗi chữ số sao cho không tồn tại hoặc không có phần mở rộng độ dài; nó là một điều không thể toán học Một lược đồ cụ thể được điều chỉnh cho loại chuỗi đầu vào mà bạn mong đợi có thể tồn tại (nhưng vì bạn không cho biết loại chuỗi nào bạn có thể gặp phải, không ai có thể giúp bạn về điều này).


1
+1, giải thích tuyệt vời. Tôi không biết về =/ ==có liên quan đến độ dài phải là bội số của 4. Tôi có thể giải quyết vấn đề này cho nhu cầu của mình
Abe Miessler

Tâm trí bạn, điều này giả sử thiếu pigeonholes. Unicode có rất nhiều chữ cái. Chúng tôi thực sự cần một sự hiểu biết tốt hơn về vấn đề thực sự .
MSalters

@Tom bạn đã tính hệ số mở rộng chiều dài trung bình bằng cách sử dụng phân chia nhật ký như thế nào? Dựa trên sơ đồ trong en.wikipedia.org/wiki/Base64 , hoàn toàn có ý nghĩa trực quan rằng với mỗi char không được mã hóa, phải mất 4/3 ký tự trong Base64 để thể hiện. Chỉ tự hỏi làm thế nào bạn đi đến kết luận tương tự với toán học ... cảm ơn :)
Jonathan Lin

Câu hỏi tồi, ngu ngốc của tôi. log (256) = 8 bit, log (64) = 6 bit, do đó tỷ lệ là 8/6 = 4/3 = 1.333 cho Base64. Chúc mừng.
Jonathan Lin

4

Ký tự mã hóa lại thường được thực hiện khi hệ thống nhận không thể xử lý chúng. Ví dụ, BASE64 đại diện cho dữ liệu bằng cách sử dụng 6 bit (2 6 , do đó 64) ký tự để biểu thị các chuỗi dữ liệu dài hơn (đôi khi "==" xuất hiện ở cuối là phần đệm để căn chỉnh). Điều này là do tệp hình ảnh của bạn trong email có thể có 0xFE trong đó và máy chủ thư của bạn sẽ không hài lòng khi truyền nó (hoặc bất kỳ ký tự không in truyền thống nào khác).

Không có mã hóa "giảm kích thước." Mã hóa chỉ là ánh xạ của các bit đến ký tự mà chúng đại diện. Điều đó nói rằng, ASCII là một bộ ký tự 7 (mã hóa) thường được lưu trữ trong 8 bit không gian. Nếu bạn giới hạn phạm vi mà bạn chấp nhận, bạn cũng có thể loại bỏ các ký tự điều khiển.

Sử dụng phương pháp này có nghĩa là bạn phải viết ra mọi thứ ở cấp độ bit, và nó cũng đóng một chút địa ngục với tốc độ và hướng dẫn của máy vì tất cả các máy hiện đại đều có sự sắp xếp là bội số của 8 bit. Ví dụ, đó là lý do tại sao Unicode là UTF-8, UTF-16 và UTF-32.

Nếu bạn đang làm điều này để bảo mật (đó là lý do tại sao bạn đăng nó trên Security.SE, phải không?), Chỉ cần lọc mọi thứ và lưu trữ chúng bình thường. Nếu bạn đang làm điều này để tiết kiệm dung lượng, hãy xem xét liệu tất cả các mã bổ sung và thời gian truy cập chậm hơn (vì hầu hết các mục nhập sẽ vượt qua ranh giới địa chỉ) có đáng để tiết kiệm không gian hay không.

Nhân tiện, sau đây là đoạn trích từ khóa học CS nơi chúng tôi phải chuyển đổi ASCII từ bộ lưu trữ 8 bit thành 7 bit:

    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

Bạn có thể nén dữ liệu với ví dụ gzip, bzip2 hoặc lzma và sau đó chạy qua base64 để giới hạn bộ ký tự được sử dụng. Điều này chỉ có lợi trên các chuỗi lớn hơn từ hàng trăm byte trở lên.


1

Tại sao không sử dụng nén LZ? đây có thể là một cách tốt để nén một chuỗi, nhưng sẽ hiệu quả hơn trong trường hợp chuỗi dài. Bao lâu là chuỗi mục tiêu bạn muốn mã hóa?


Làm thế nào để nén LZ so sánh với gzip hoặc bzip2 được đề cập trong đề xuất attir?
NoChance

gzip được xây dựng trên LZ và Huffman Coding. thêm về LZ en.wikipedia.org/wiki/LZ77
A.Rashad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.