Thwart nén LZMA2


11

Mục tiêu

Tạo một chương trình hoặc cặp chương trình phá vỡ tập thể và sửa chữa các tệp với mục đích ngăn LZMA2 hoạt động hiệu quả. Các thói quen phá vỡ và sửa lỗi phải có đi có lại, vì vậy bạn có thể khôi phục chính xác tệp gốc.

Mục tiêu

Phương pháp nén

  • Ubuntu / liên quan: xz -kz5 <infile>
  • Các cửa sổ: 7z.exe a -txz -mx5 <outfile> <infile>
  • Khác: Sử dụng máy nén LZMA2 với mức nén 5 để nén các tác phẩm của Shakespeare thành 1570550 byte ± 100 byte.

Ghi điểm; tổng của (mọi thứ đều tính bằng byte ls -lhoặc dirnó):

  • Kích thước (các) chương trình (bất cứ điều gì cần thiết để có thể đảo ngược "phá vỡ" / sửa tệp)
  • Sự khác biệt về kích thước (tuyệt đối) giữa:
    • Các tác phẩm được thu thập thô của Shakespeare và bản sao (không nén) đã sửa đổi của bạn.
    • Ảnh thô và bản sao sửa đổi (không nén) của bạn.
  • Sự khác biệt về kích thước hoặc 0, tùy theo giá trị nào lớn hơn giữa:
    • Các tác phẩm được thu thập thô của Shakespeare trừ đi bản sao nén LZMA2 đã sửa đổi của bạn.
    • Ảnh thô trừ bản sao nén LZMA2 đã sửa đổi của bạn.

Thí dụ

Ví dụ về điểm kém, chơi golf lười biếng, nhưng tuân thủ Python 2.x:

import sys
x = 7919 if sys.argv[1] == 'b' else -7919
i = bytearray(open(sys.argv[2], 'rb').read())
for n in range(len(i)):
    i[n] = (i[n] + x*n) % 256
o = open(sys.argv[2]+'~', 'wb').write(i)

Đang chạy...

$ python break.py b pg100.txt 
$ python break.py f pg100.txt~ 
$ diff -s pg100.txt pg100.txt~~
Files pg100.txt and pg100.txt~~ are identical
$ python break.py b Glühwendel_brennt_durch.jpg 
$ python break.py f Glühwendel_brennt_durch.jpg~
$ diff -s Glühwendel_brennt_durch.jpg Glühwendel_brennt_durch.jpg~~
Files Glühwendel_brennt_durch.jpg and Glühwendel_brennt_durch.jpg~~ are identical
$ xz -kz5 pg100.txt~
$ xz -kz5 Glühwendel_brennt_durch.jpg~
$ ls -ln
-rw-rw-r-- 1 2092 2092     194 May 23 17:37 break.py
-rw-rw-r-- 1 2092 2092 1659874 May 23 16:20 Glühwendel_brennt_durch.jpg
-rw-rw-r-- 1 2092 2092 1659874 May 23 17:39 Glühwendel_brennt_durch.jpg~
-rw-rw-r-- 1 2092 2092 1659874 May 23 17:39 Glühwendel_brennt_durch.jpg~~
-rw-rw-r-- 1 2092 2092 1646556 May 23 17:39 Glühwendel_brennt_durch.jpg~.xz
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:24 pg100.txt
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:39 pg100.txt~
-rw-rw-r-- 1 2092 2092 5589891 May 23 17:39 pg100.txt~~
-rw-rw-r-- 1 2092 2092 3014136 May 23 17:39 pg100.txt~.xz

Ghi bàn

  • = 194 + abs (5589891 - 5589891) + tối đa (5589891 - 3014136, 0) + abs (1659874 - 1659874) + tối đa (1659874 - 1646556, 0)
  • = 194 + 0 + 2575755 + 0 + 13318
  • 2.589.267 byte. Xấu, nhưng không làm gì với các tệp mang lại số điểm 4.635.153 byte.

Làm rõ

Đây là golf, vì vậy bạn đang cố gắng giảm thiểu điểm số của mình. Tôi không chắc liệu các bình luận có chỉ ra một lỗ hổng hợp pháp trong việc chấm điểm của tôi hay không nếu chúng là do tôi làm cho nó quá phức tạp. Trong mọi trường hợp, bạn muốn NHỎ :

  • mã nguồn
  • sự khác biệt giữa tệp sửa đổi không nén và tệp gốc (ví dụ: nếu bạn sửa đổi nó bằng cách nối thêm một nghìn tỷ 0 vào cuối, điểm số của bạn chỉ tăng lên một nghìn tỷ byte)
  • sự khác biệt giữa tệp được sửa đổi nén và tệp gốc (ví dụ: các tệp càng trở nên không thể nén được, điểm của bạn càng cao). Một tập tin hoàn toàn không thể nén mà tăng nhẹ hoặc không hoàn toàn sẽ có điểm 0.

2
Câu trả lời trolling: Bước 1 - tính xem bạn có bao nhiêu dung lượng đĩa trống, sau đó chia số đó cho kích thước của tệp để lấy N. Bước 2 - nối tệp vào chính nó N lần và nối số N. Bước 3 - nhận ra có không còn chỗ trống để nén tệp nhưng kết thúc với sự khác biệt tuyệt đối về kích thước tệp của một vài terrabyte (hoặc hơn) .... [Để đảo ngược, đọc N từ cuối tệp và thu nhỏ tệp xuống 1 / Nth kích thước. ]
MT0

@ MT0: Ah tôi nghĩ giải pháp là sự khác biệt không nên tuyệt đối. Nếu tệp sửa đổi của bạn lớn hơn sẽ bị trừ điểm.
Claudiu

@ MT0 nếu bạn sửa đổi tệp để biến nó thành một terabyte lớn, thì điểm của bạn sẽ là 1 terabyte ... khá tệ khi bạn đang cố gắng chơi gôn.
Nick T

@ MT0 Tôi đã thêm một làm rõ cho bài viết, điều đó có giúp gì không?
Nick T

2
Một ngụy biện. Máy nén có thể tạo một tệp lớn hơn nếu t đặc biệt không thể nén được. Trong trường hợp này bạn nên được khen thưởng, không bị trừng phạt, không?
Claudiu

Câu trả lời:


8

Con trăn, điểm = 120

import sys,hashlib
i=0
for c in sys.stdin.read():sys.stdout.write(chr(ord(c)^ord(hashlib.md5(str(i)).digest()[0])));i+=1

Tạo một bảng đệm một lần bằng md5 ở chế độ bộ đếm . xors các tập tin với nó. Điều này có lợi thế là các tệp gốc và tệp bị phá vỡ có cùng kích thước và bộ ngắt và bộ sửa lỗi là cùng một chương trình.

Các tập tin bị gián đoạn nén lớn hơn bản gốc.


Tôi đã điều chỉnh cách tính điểm để nếu các tệp được nén lớn hơn so với các đối tác ban đầu của chúng, bạn sẽ không bị phạt và chúng chỉ đạt điểm 0. Không chắc chắn cách khác biệt đối với các tệp của bạn nhưng bạn có thể muốn cập nhật điểm
Nick T

@NickT: đã cập nhật.
Keith Randall

8

C, 51 = 51 + 0 + 0 + 0 + 0

main(c){for(;c=~getchar();putchar(~c^rand()>>23));}

Theo các thủ thuật golf , chương trình này lặp lại cho từng byte trong đầu vào tiêu chuẩn và không độc quyền - hoặc với một phần đệm vô hạn từ rand (). Tôi đã thử nghiệm điều này với rand () trong libc của OpenBSD 5.5.

Sử dụng:

./scramble <orig >scrambled
./scramble <scrambled >orig.copy

Để kiểm tra chương trình của tôi, tôi đã viết một kịch bản shell test.sh (57 dòng) để biên dịch chương trình của tôi và tính điểm của tôi.

$ sh test.sh
[1/4] Compiling scramble...
/tmp//ccbcB43x.o(.text+0x6): In function `main':
: warning: rand() isn't random; consider using arc4random()
[2/4] Scrambling files...
[3/4] Compressing scrambled files...
[4/4] Checking descrambler...
SCORE: 51=51+0+0+0+0
You may wish to rm -rf tmp.9Tjw89dgCs
$ ls -l tmp.9Tjw89dgCs/
total 43032
-rw-r--r--  1 kernigh  kernigh  1659874 May 28 17:23 filament.jpg.cp
-rw-r--r--  1 kernigh  kernigh  1659874 May 28 17:23 filament.jpg.sc
-rw-r--r--  1 kernigh  kernigh  1660016 May 28 17:23 filament.jpg.sc.xz
-rw-r--r--  1 kernigh  kernigh  5589891 May 28 17:23 pg100.txt.cp
-rw-r--r--  1 kernigh  kernigh  5589891 May 28 17:23 pg100.txt.sc
-rw-r--r--  1 kernigh  kernigh  5590232 May 28 17:23 pg100.txt.sc.xz
-rwxr-xr-x  1 kernigh  kernigh     8564 May 28 17:23 scramble

Ghi chú về rand () và dịch chuyển đúng

Bất kỳ thuật toán nén nào cũng không thể nén dữ liệu ngẫu nhiên. Tôi có thể ngụy trang pg100.txtfilament.jpg thành dữ liệu ngẫu nhiên nếu tôi xáo trộn chúng bằng mật mã luồng .

Ý tưởng đầu tiên của tôi là độc quyền - hoặc bản rõ bằng pad để tạo bản mã , sau đó lưu trữ cả bản mã và phần đệm trong tệp được xáo trộn. Điều này sẽ tăng kích thước của tệp và tăng điểm của tôi. Sự lựa chọn rõ ràng là sử dụng cùng một bảng cho mỗi tệp và chỉ lưu trữ bản mã trong tệp được xáo trộn. Nếu tôi chỉ gọi rand (), nó sử dụng hạt giống mặc định là 1 và tạo cùng một pad mỗi lần.

OpenBSD 5.5 định nghĩa rand () trong stdlib.hrand.c :

/* from stdlib.h */
#define RAND_MAX    0x7fffffff

/* from rand.c */
static u_int next = 1;

int
rand_r(u_int *seed)
{
    *seed = *seed * 1103515245 + 12345;
    return (*seed % ((u_int)RAND_MAX + 1));
}

int
rand(void)
{
    return (rand_r(&next));
}

Đây là một máy phát đồng quy tuyến tính . Lỗ hổng lớn là các bit thấp có chu kỳ ngắn. Bit thứ 1 có chu kỳ là 2: nếu bạn lật một đồng xu rand()&1, nó sẽ đi đầu, đuôi, đầu, đuôi, v.v. Bit thứ n có chu kỳ 2 n . Có 31 bit, vì vậy toàn bộ chuỗi có chu kỳ 2 31 .

LZMA2 có thể tìm thấy các mẫu trong thời gian ngắn và nén chúng. Mã ngắn nhất ~c^rand()lấy 8 bit thấp và không ngăn chặn nén. Sự thay đổi đúng trong ~c^rand()>>9giúp đỡ, nhưng không đủ. Tôi sử dụng ~c^rand()>>23.

  • ~c ĐIỂM: 4227957 = 40 + 0 + 0 + 4019391 + 208526
  • ~c^rand() ĐIỂM: 2474616 = 47 + 0 + 0 + 2463735 + 10834
  • ~c^rand()>>9 ĐIỂM: 350717 = 50 + 0 + 0 + 350667 + 0
  • ~c^rand()>>23 ĐIỂM: 51 = 51 + 0 + 0 + 0 + 0

5

BrainFuck : 129 (129 + 0 + 0 + 0 + 0) *

Random.bf (linefeed được thêm vào để dễ đọc)

,+[->>>>++[<++++++++[<[<++>-]>>[>>]+>>+[-[->>+<<<[<[<<]<
+>]>[>[>>]]]<[>>[-]]>[>[-<<]>[<+<]]+<<]<[>+<-]>>-]<[-<<+
>>]<<.,+[->]>>>]]

Để tạo, unrandom.bfbạn cần thay đổi + cuối cùng trong dòng thứ hai.

Hầu hết các mã dựa trên trình tạo số ngẫu nhiên dựa trên Rule30 của Daniel B Cristofani được điều chỉnh để thêm số vào mỗi đầu vào và chấm dứt khi không còn đầu vào nữa.

* Tôi đã kiểm tra các byte mà nó đã xử lý cho đến nay là 212992 (được xử lý sau 12 giờ) và cả hai tệp đều biến thành tệp nén 213064. Tôi đoán có thể được thực hiện vào cuối tuần để biết chắc chắn nhưng tôi không muốn chờ đợi để đăng. Tôi sẽ cập nhật điểm nếu sai, nhưng hãy giữ giải pháp kể từ khi Rule30 đá!

Thông tin bên lề: Quy tắc 30 được phát hiện bởi Stephen Wolfram vào năm 1983 và theo Wikipedia, nó được sử dụng để sản xuất các số nguyên ngẫu nhiên trong Mathematica.

Biên dịch và chạy:

Nó sử dụng thời gian và không gian theo cấp số nhân (lặp lại hơn 32 ô trên mỗi char được xử lý) vì vậy nó yêu cầu thời gian chạy BrainFuck có ít nhất 178.876.517 ô để mã hóa tệp Shakespear, không coi non ascii là unicode, có nhiều hơn 8 bit và sử dụng -1 dưới dạng eof (khác nhau giữa 255 và -1). Tôi thường sử dụng thông dịch viên người khác nhưng lần này tôi cần phải là người cắm và quảng bá cho riêng mình:

jitbf --eof -1 -b 16 -c 200000000 random.bf < pg100.txt > pg100.txt.ran
jitbf --eof -1 -b 16 -c 200000000 random.bf < Glühwendel_brennt_durch.jpg > Glühwendel_brennt_durch.jpg.ran

jitfb biên dịch BrainFuck để tối ưu hóa C và lạm dụng perl Inline :: C để chạy nó. Đó là gói với trình biên dịch BrainFuck mở rộng của tôi . Với kích thước và chiều rộng của ô trong đối số, nó sẽ phân bổ khoảng 400MB.


3

CJam, 22 byte

G,~q{5$H$+255%_@^o}/];

Điều này sử dụng một trình tạo Fibonacci bị trễ với mối quan hệ lặp lại s n = (s n-5 + s n-16 )% 255 (mà tôi đã chọn do nhầm lẫn, tuy nhiên nó vẫn hoạt động) và một hạt giống tầm thường để tạo ra một luồng byte giả ngẫu nhiên , mà sau đó XOR với đầu vào.

Tôi đã kiểm tra mã của mình với CJam 0.6 , được xuất bản vào ngày 1 tháng 5 năm 2014.

Làm thế nào nó hoạt động

G,~                    e# Dump 0, 1, ... and 15 on the stack.
   q                   e# Read from STDIN.
    {             }/   e# For each character in the input.
     5$H$              e# Copy the sixth and 19th element from the stack.
         +255%         e# Push their sum modulo 255.
              _@       e# Duplicate and rotate the character on top.
                ^o     e# XOR and print.
                    ]; e# Clear the stack.

Ghi bàn

$ LANG=en_US
$ alias cjam='java -jar /usr/local/share/cjam/cjam-0.6.jar'
$ cjam thwart.cjam < pg100.txt > pg100.txt~
$ cjam thwart.cjam < pg100.txt~ > pg100.txt~~
$ diff -s pg100.txt pg100.txt~~
Files pg100.txt and pg100.txt~~ are identical
$ cjam thwart.cjam < Gluehwendel_brennt_durch.jpg > Gluehwendel_brennt_durch.jpg~
$ cjam thwart.cjam < Gluehwendel_brennt_durch.jpg~ > Gluehwendel_brennt_durch.jpg~~
$ diff -s Gluehwendel_brennt_durch.jpg Gluehwendel_brennt_durch.jpg~~
Files Gluehwendel_brennt_durch.jpg and Gluehwendel_brennt_durch.jpg~~ are identical
$ xz -kz5 pg100.txt~ Gluehwendel_brennt_durch.jpg~
$ wc -c thwart.cjam pg100.txt* Gluehwendel_brennt_durch.jpg*
      22 thwart.cjam
 5589889 pg100.txt
 5589889 pg100.txt~
 5589889 pg100.txt~~
 5590232 pg100.txt~.xz
 1659874 Gluehwendel_brennt_durch.jpg
 1659874 Gluehwendel_brennt_durch.jpg~
 1659874 Gluehwendel_brennt_durch.jpg~~
 1660016 Gluehwendel_brennt_durch.jpg~.xz
28999559 total

3

PHP, 117 + 0 + 0 + 0 + 0 = 117

Bởi vì bạn có thực sự giao phó nhiệm vụ thu thập dữ liệu của bạn ngoài sự công nhận với bất kỳ ngôn ngữ nào khác không?

<?=substr(gmp_export(gmp_invert(2*gmp_import($s=stream_get_contents(STDIN))+1,$m=2*gmp_pow(256,strlen($s)))/2+$m),1);

Mặc dù tất cả các giải pháp khác đều dựa trên các cấu trúc bảo mật của trực tuyến, như các bộ tạo số ngẫu nhiên, hay bộ mã hóa cấp quân sự, hay, nhưng giải pháp này chỉ đơn giản diễn giải các chuỗi là đại diện cho các số lẻ modulo 2⋅256 ^ và tính toán nghịch đảo mô đun của chúng .

Bản giới thiệu:

$ php thwart.php < 100.txt.utf-8 > 100.txt.utf-8~
$ php thwart.php < 100.txt.utf-8~ > 100.txt.utf-8~~
$ diff -s 100.txt.utf-8 100.txt.utf-8~~
Files 100.txt.utf-8 and 100.txt.utf-8~~ are identical
$ php thwart.php < Glühwendel_brennt_durch.jpg > Glühwendel_brennt_durch.jpg~
$ php thwart.php < Glühwendel_brennt_durch.jpg~ > Glühwendel_brennt_durch.jpg~~
$ diff -s Glühwendel_brennt_durch.jpg Glühwendel_brennt_durch.jpg~~
Files Glühwendel_brennt_durch.jpg and Glühwendel_brennt_durch.jpg~~ are identical
$ xz -kz5 100.txt.utf-8~ Glühwendel_brennt_durch.jpg~
$ wc -c *
 5589889 100.txt.utf-8
 5589889 100.txt.utf-8~
 5590232 100.txt.utf-8~.xz
 5589889 100.txt.utf-8~~
 1659874 Glühwendel_brennt_durch.jpg
 1659874 Glühwendel_brennt_durch.jpg~
 1660016 Glühwendel_brennt_durch.jpg~.xz
 1659874 Glühwendel_brennt_durch.jpg~~
     117 thwart.php
28999654 total

2

kịch bản shell, 203

id|gpg --batch --passphrase-fd 0 --personal-compress-preferences Uncompressed $1 $2

Chạy nó:

% sh break.sh -c pg100.txt                       
% sh break.sh -d pg100.txt.gpg > pg100.txt-original
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
% diff -s pg100.txt pg100.txt-original
Files pg100.txt and pg100.txt-original are identical
% sh break.sh -c Glühwendel_brennt_durch.jpg
% sh break.sh -d Glühwendel_brennt_durch.jpg.gpg > Glühwendel_brennt_durch.jpg-original
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: WARNING: message was not integrity protected
% diff -s Glühwendel_brennt_durch.jpg Glühwendel_brennt_durch.jpg-original
Files Glühwendel_brennt_durch.jpg and Glühwendel_brennt_durch.jpg-original are identical
% xz -kz5 Glühwendel_brennt_durch.jpg.gpg 
% xz -kz5 pg100.txt.gpg 
% ls -ln
total 28340
-rw-r--r-- 1 1000 1000      84 May 24 04:33 break.sh
-rw-r--r-- 1 1000 1000 1659874 Jan 19 17:22 Glühwendel_brennt_durch.jpg
-rw-r--r-- 1 1000 1000 1659943 May 24 04:46 Glühwendel_brennt_durch.jpg.gpg
-rw-r--r-- 1 1000 1000 1660084 May 24 04:46 Glühwendel_brennt_durch.jpg.gpg.xz
-rw-r--r-- 1 1000 1000 1659874 May 24 04:46 Glühwendel_brennt_durch.jpg-original
-rw-r--r-- 1 1000 1000 5589891 May 24 03:55 pg100.txt
-rw-r--r-- 1 1000 1000 5589941 May 24 04:43 pg100.txt.gpg
-rw-r--r-- 1 1000 1000 5590284 May 24 04:43 pg100.txt.gpg.xz
-rw-r--r-- 1 1000 1000 5589891 May 24 04:43 pg100.txt-original

Không phải rất di động, nhưng có thể được thực hiện với chi phí của một vài byte. Yêu cầu PGP (cũng có thể thực hiện với OpenSSL). Có thể lưu chênh lệch ~ 50 byte giữa tệp được mã hóa và bản gốc.

Ghi điểm:

84 + abs (1659874 - 1659943) + tối đa (1659874 - 1660084, 0) + abs (5589891 - 5589941) + tối đa (5589891 - 5590284, 0) = 203


1

Con trăn, điểm = 183 + 7 + 6 + 0 + 0 = 196

Việc chấm điểm sẽ phạt bạn vì làm cho tệp hoàn toàn không bị nén, do đó tệp nén lớn hơn so với chi phí nén. Do đó, chương trình của tôi làm cho chúng hơi ít hơn hoàn toàn không thể nén được:

import sys
from random import randint as J,seed
x=sys.stdin.read()
seed(ord(x[1]))
n=int(2362*J(1,2)**2.359)
sys.stdout.write(x[:n]+''.join(chr(ord(c)^J(0,255))for c in x[n:]))

Kết quả:

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ cat photo.jpg | python break.py > photo.jpg~; cat photo.jpg~ | python break.py > photo.jpg~~; diff photo.jpg photo.jpg~~; xz -kz5 photo.jpg~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ cat pg100.txt | python break.py > pg100.txt~; cat pg100.txt~ | python break.py > pg100.txt~~; diff pg100.txt pg100.txt~~; xz -kz5 pg100.txt~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ ls -l
total 28337
----------+ 1 Laxori mkpasswd     183 2014-05-24 13:43 break.py
----------+ 1 Laxori mkpasswd 5589891 2014-05-23 19:19 pg100.txt
-rw-r--r--+ 1 Laxori mkpasswd 5589891 2014-05-24 13:45 pg100.txt~
-rw-r--r--+ 1 Laxori mkpasswd 5589884 2014-05-24 13:45 pg100.txt~.xz
-rw-r--r--+ 1 Laxori mkpasswd 5589891 2014-05-24 13:45 pg100.txt~~
----------+ 1 Laxori mkpasswd 1659874 2014-05-23 19:19 photo.jpg
-rw-r--r--+ 1 Laxori mkpasswd 1659874 2014-05-24 13:44 photo.jpg~
-rw-r--r--+ 1 Laxori mkpasswd 1659880 2014-05-24 13:44 photo.jpg~.xz
-rw-r--r--+ 1 Laxori mkpasswd 1659874 2014-05-24 13:44 photo.jpg~~

Laxori@Laxori-PC /cygdrive/f/Programming/lzkill
$ python
Python 2.5.2 (r252:60911, Dec  2 2008, 09:26:14)
[GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 183 + abs(5589891-5589884) + abs(1659874-1659880)
196

Với các quy tắc hiện hành, không có hình phạt nào cho một tệp nén lớn hơn. Các quy tắc đã thay đổi? Nếu vậy, thay đổi như vậy là không công bằng cho chương trình này.
hạt nhân

@kernigh: Vâng họ đã thay đổi sau khi tôi đăng nó. Thực sự họ nên có được như bây giờ ngay từ đầu.
Claudiu
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.