LZMA2 압축 방지


11

LZMA2가 효과적으로 작동하지 못하게하기 위해 파일을 집합 적으로 방해하고 수정하는 프로그램 또는 프로그램 쌍을 만듭니다. 중단 및 수정 루틴은 역수 여야하므로 원본 파일을 정확하게 복구 할 수 있습니다.

목표

압축 방법

  • 우분투 / 관련 : xz -kz5 <infile>
  • 윈도우 : 7z.exe a -txz -mx5 <outfile> <infile>
  • 기타 : 셰익스피어의 작품을 1570550 바이트 ± 100 바이트로 압축하는 압축 레벨 5의 LZMA2 압축기를 사용하십시오.

채점; 합계 (모든 바이트에, ls -l또는 dir그것을) :

  • 프로그램 크기 (파일을 가역적으로 "중단"/ 수정하기 위해 필요한 모든 것)
  • 다음의 크기 차이 (절대) :
    • 셰익스피어의 원본 수집 작품 및 수정 된 (압축되지 않은) 사본.
    • 원본 사진 및 수정 된 (압축되지 않은) 사본.
  • 크기의 차이 또는 0 중 큰 값 :
    • 셰익스피어에서 수집 한 원본 작품에서 수정 된 LZMA2 압축 사본을 뺀 값.
    • 원본 사진에서 수정 된 LZMA2 압축 사본을 뺀 값입니다.

불완전한 점수, 게 으르면서 골치 아픈 파이썬 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)

달리는...

$ 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

점수

  • = 194 + abs (5589891-5589891) + 최대 (5589891-3014136, 0) + abs (1659874-1659874) + 최대 (1659874-1646556, 0)
  • = 194 + 0 + 2575755 + 0 + 13318
  • 2,589,267 바이트 나쁘지만 파일에 아무것도 수행하지 않으면 4,635,153 바이트의 점수를 얻습니다.

설명

이것은 골프이므로 점수 를 최소화 하려고합니다 . 의견이 내 점수에 합법적 인 구멍을 지적하는지 또는 너무 복잡하게 만들 었는지 확실하지 않습니다. 어쨌든 가장 작은 것을 원합니다 .

  • 소스 코드
  • 압축되지 않은 수정 된 파일과 원본 파일의 차이 (예 : 끝에 1 조의 0을 추가하여 수정하면 점수는 1 조 바이트 증가)
  • 압축 된 수정 된 파일과 원본 파일의 차이 (예 : 파일이 압축되지 않을수록 점수가 높아짐) 약간 커지거나 전혀 커지지 않는 완벽하게 압축 할 수없는 파일은 0 점을 얻습니다.

2
트롤링 답변 : 1 단계-사용 가능한 디스크 공간을 계산 한 다음 N을 얻기 위해 파일 크기로 나눕니다. 2 단계-파일을 N 번 추가하고 숫자 N을 추가하십시오. 파일을 압축하는 데 남은 공간은 없지만 몇 테라 바이트 (또는 그 이상)의 파일 크기 차이로 끝납니다 .... [역으로 바꾸려면 파일 끝에서 N을 읽고 파일을 1 / N 크기로 줄입니다. ]
MT0

@ MT0 : 아아, 해결책은 차이가 절대적인 것이 아니라고 생각합니다 . 수정 된 파일이 크면 포인트를 빼야합니다.
Claudiu

@ MT0 파일을 테라 바이트 크기로 수정하면 골프를 치려고 할 때 점수가 1 테라 바이트가됩니다.
Nick T

@ MT0 게시물에 설명을 추가했는데 도움이 되나요?
Nick T

2
한 번의 떨림. t를 압축 할 수없는 경우 압축기가 더 큰 파일을 만들 수 있습니다. 이 경우, 처벌받지 말고 보상을 받아야합니다.
Claudiu

답변:


8

파이썬, 점수 = 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

카운터 모드 에서 md5를 사용하여 일회용 패드를 만듭니다 . 파일과 함께 xors. 이는 원본 파일과 중단 된 파일의 크기가 동일하고 중단 자와 수정 프로그램이 동일한 프로그램이라는 장점이 있습니다.

압축 된 파일은 원본보다 큽니다.


압축 된 파일이 원래의 파일 보다 큰 경우 점수를 조정하여 불이익을받지 않고 점수 만 0으로 표시합니다. 파일의 차이가 어떤지 확실하지 않지만 점수를 업데이트 할 수 있습니다.
Nick T

@NickT : 업데이트되었습니다.
Keith Randall

8

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

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

golf tricks 아래 에서이 프로그램은 표준 입력에서 각 바이트마다 반복되며 rand ()의 독점 패드 또는 배타적 패드로 수행됩니다. OpenBSD 5.5의 libc에서 rand ()로 이것을 테스트했습니다.

용법:

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

프로그램을 테스트하기 위해 프로그램 을 컴파일하고 점수를 계산 하는 쉘 스크립트 test.sh (57 줄) 를 작성했습니다.

$ 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

rand () 및 올바른 시프트에 대한 참고 사항

압축 알고리즘은 임의의 데이터를 압축 할 수 없습니다. 스트림 암호로 스크램블하면 pg100.txtfilament.jpg 를 임의의 데이터로 위장 할 수 있습니다 .

첫 번째 아이디어는 ciphertext 를 만들기 위해 pad 로 독점 텍스트 또는 일반 텍스트작성한 다음 암호문pad 를 스크램블 파일에 저장하는 것이 었습니다 . 파일 크기가 커지고 점수가 높아집니다. 확실한 선택은 모든 파일에 대해 동일한 패드 를 사용 하고 스크램블 된 파일에 암호문 만 저장하는 것 입니다. 방금 rand ()를 호출하면 기본 시드 1을 사용하고 매번 같은 패드를 만듭니다 .

OpenBSD 5.5는 stdlib.hrand.c 에 rand ()를 정의합니다 :

/* 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));
}

이것은 선형 합동 발생기 입니다. 가장 큰 결점은 낮은 비트의주기가 짧다는 것입니다. 첫 번째 비트의주기는 2입니다.로 동전을 뒤집 으면 rand()&1머리, 꼬리, 머리, 꼬리 등으로 이동합니다. n 번째 비트의주기는 2 n 입니다. 31 비트가 있으므로 전체 시퀀스의주기는 2 31 입니다.

LZMA2는 짧은 시간 안에 패턴을 찾아 압축 할 수 있습니다. 가장 짧은 코드 ~c^rand()는 낮은 8 비트를 취하며 압축을 방지하지 않습니다. 올바른 변화는 ~c^rand()>>9도움이되지만 충분하지는 않습니다. 사용 ~c^rand()>>23합니다.

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

5

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

random.bf (가독성을 위해 추가 된 줄 바꿈)

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

만들려면 unrandom.bf두 번째 줄에서 마지막 +를 변경해야합니다.

대부분의 코드는 Daniel B Cristofani의 Rule30 기반 난수 생성기를 기반으로 하며 각 입력에 숫자를 추가하고 더 이상 입력이 없을 때 종료됩니다.

* 지금까지 처리 한 바이트를 212992 (12 시간 후 처리)로 테스트했으며 두 파일 모두 213064 압축 파일로 바뀝니다. 나는 확실히 알고 있기 위해 일주일 말까지 완료 될 수 있다고 생각하지만 게시를 기다리고 싶지 않습니다. 점수가 틀리면 점수를 업데이트하되 Rule30이 끝나기 때문에 솔루션을 유지하십시오!

퀴즈 : 규칙 30 은 1983 년 Stephen Wolfram에 의해 발견되었으며 Wikipedia에 따르면 Mathematica에서 임의의 정수를 생성하는 데 사용됩니다.

컴파일 및 실행

지수 시간과 공간을 사용하여 (처리 된 문자 당 32 개 이상의 셀을 반복합니다) 셰익스피어 파일을 인코딩하기 위해 적어도 178,876,517 개의 셀을 가진 BrainFuck 런타임이 필요하며 비 ASCII를 유니 코드로 취급하지 않으며 8 비트 셀보다 넓고 -1을 eof로 (255와 -1 사이에서 다름) 나는 보통 다른 사람들의 통역사를 사용하지만 이번에는 플러그가되어 내 자신을 홍보해야합니다.

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는 BrainFuck을 최적화 된 C로 컴파일하고 perl Inline :: C를 악용하여 실행합니다. Extended BrainFuck 컴파일러 와 함께 번들로 제공됩니다 . 인수에 셀 크기와 너비가 있으면 약 400MB가 할당됩니다.


3

CJam, 22 바이트

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

이것은 반복 관계 s n = (s n-5 + s n-16 ) % 255 (실수로 선택했지만 그럼에도 불구하고 작동합니다)와 임의의 시드를 사용하여 의사 랜덤 바이트 스트림을 생성 하는 지연 피보나치 생성기 를 사용 합니다 입력과 XOR합니다.

2014 년 5 월 1 일에 게시 된 CJam 0.6으로 코드를 테스트했습니다 .

작동 원리

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.

점수

$ 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

데이터를 다른 언어로 인식하는 것 이상으로 데이터를 관리하는 작업을 실제로 맡겨야합니까?

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

다른 모든 솔루션은“임의 숫자 생성기”또는“군사 등급 암호화”와 같은“안전한”구성을 기반으로하는 반면,이 방법은 단순히 문자열을 홀수로 표현하는 모듈로 2⋅256 ^ 길이로 해석하고 모듈 식 역수를 계산합니다 .

데모:

$ 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

쉘 스크립트, 203

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

그것을 실행 :

% 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

휴대가 쉽지는 않지만 몇 바이트의 비용으로 만들 수 있습니다. PGP가 필요합니다 (OpenSSL을 통한 구현도 가능합니다). 인코딩 된 파일과 원본 사이의 ~ 50 바이트 차이를 저장할 수 있습니다.

채점 :

84 + abs (1659874-1659943) + 최대 (1659874-1660084, 0) + abs (5589891-5589941) + 최대 (5589891-5590284, 0) = 203


1

파이썬, 점수 = 183 + 7 + 6 + 0 + 0 = 196

압축 파일은 압축 오버 헤드보다 크기 때문에 점수를 매기면 파일을 완전히 압축 할 수 없게됩니다. 따라서 내 프로그램은 완전히 압축 할 수없는 것보다 약간 작습니다.

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:]))

결과:

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

현재 규칙을 사용하면 압축 파일 크기가 더 커질 수 있습니다. 규칙이 바뀌 었습니까? 그렇다면 그러한 변경은이 프로그램에 불공평했습니다.
kernigh

@ kernigh : 예, 게시 한 후에 변경되었습니다. 진실로 그들은 지금부터 시작했던 방식이어야했다.
Claudiu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.