암호 세이버 암호화


11

아래 설명 된대로 CipherSaber 암호화 프로그램을 구현하십시오 . 지침 :

  • 가장 작은 항목 (바이트)이 이깁니다.
    • 그러나 규범 에서 벗어난 경우, 골프 항목이 심각하지 않더라도 흥미로운 항목을 게시 할 수 있습니다.
  • 항목은 일반적으로 표준 입력에서 일반 텍스트를 가져 와서 원하는 방식으로 사용자가 지정한 키를 사용하여 암호문을 표준 출력에 기록하는 프로그램입니다.
    • 그러나 이것을 절차로 구현하려면 괜찮습니다.
  • IV는 암호로 안전한 의사 난수 생성기에서 가져와야합니다. 해당 언어가 지원하지 않으면 다른 언어를 선택하십시오. ;-)
  • 암호화 관련 라이브러리, 시스템 호출 또는 명령어 (위에 명시된 PRNG 이외)를 사용하지 마십시오. 물론, 일반적인 하위 수준의 비트 단위 연산은 괜찮습니다.

CipherSaber는 RC4 / Arcfour의 변형이므로 후자를 설명하는 것으로 시작한 다음 CipherSaber가 변경 한 사항을 설명하겠습니다.

0. RC4 / 아크 포

Arcfour는 다른 곳 에서 완전히 지정 되었지만 완전성을 위해 여기에 설명하겠습니다. (인터넷 초안과이 설명 사이에 불일치가있는 경우 전자는 표준입니다.)

키 설정

두 배열을 설정, SS2길이 256, 둘, k_1키의 첫 번째 바이트이고, k_n마지막이다.

S = [0, ..., 255]
S2 = [k_1, ..., k_n, k_1, ...]

( S2모든 256 바이트가 채워질 때까지 키의 바이트로 반복해서 채워집니다.)

그런 다음 j0으로 초기화 하고 256 번 셔플하십시오.

j = 0
for i in (0 .. 255)
    j = (j + S[i] + S2[i]) mod 256
    swap S[i], S[j]
end

이것으로 키 설정이 완료되었습니다. S2배열은 더 이상 여기에 사용되지 않으며, 세정 할 수있다.

암호 스트림 생성

초기화 i하고 j0으로 설정 한 후 다음과 같이 키 스트림을 생성하십시오.

i = 0
j = 0
while true
    i = (i + 1) mod 256
    j = (j + S[i]) mod 256
    swap S[i], S[j]
    k = (S[i] + S[j]) mod 256
    yield S[k]
end

데이터 암호화 / 복호화

  • 암호화하려면 일반 텍스트와 함께 키 스트림 출력을 XOR하십시오.
  • 암호 해독을 위해 키 스트림 출력을 암호문과 함께 XOR

1. 암호 세이버

CipherSaber (이 질문에서 우리가 구현하고있는 것)는 두 가지 방식으로 RC4 / Arcfour의 변형입니다.

10 바이트 IV / 초급

메시지를 암호화 할 때 via와 같은 10 개의 임의 바이트를 가져 /dev/urandom와서 암호화 된 출력의 처음 10 바이트에 기록해야합니다. 메시지를 해독 할 때 입력의 처음 10 바이트는 메시지를 암호화하는 데 사용되는 IV입니다.

RC4 / Arcfour 키 설정 단계는 키로 실행되며 passphrase || IV, 여기서 passphrase사용자 지정 암호 IV는 위에서 설명한대로 ||연결되어 있습니다. "Hello, world!"의 암호입니다. "supercalif"의 IV (단, -P 일 가능성은 낮음)는 "Hello, world! supercalif"의 키가됩니다.

키 설정의 여러 반복

WEP 암호화를 완전히 손상시킨 취약점을 방지하기 위해 RC4의 주요 설정 단계에있는 셔플 링 루프는 사용자가 지정한 횟수만큼 실행됩니다. j반복 사이에 값을 유지해야합니다.

2. 시험 벡터

다음은 프로그램을 테스트하는 데 사용할 수 있는 몇 가지 테스트 벡터 입니다. 또한 squeamish ossifrage 는 결과의 유효성을 검사하는 데 사용할 수 있는 CipherSaber 암호화 및 암호 해독 도구 를 만들었습니다 .

암호화 프로그램 만 구현하면됩니다. 암호 해독 프로그램을 제공 할 필요는 없지만 올바른 키를 사용하여 올바르게 구현 된 암호 해독 프로그램으로 처리 할 경우 암호 프로그램의 출력이 원래 입력으로 올바르게 왕복해야합니다.

답변:


7

Pyth, 100 바이트

$import os$KsM$os.urandom(10)$JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256=Z0sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

이 스크립트는 $명령을 사용하여 Python 코드를 실행할 수 있습니다. 서버에서 악성 코드가 실행되는 것을 방지하기 위해이 명령은 온라인 컴파일러에서 비활성화됩니다. 여기에서 찾을 수있는 오프라인 컴파일러로 실행해야 합니다 .

입력 형식은 다음과 같습니다.

secret key
5 (number of repeats)
secret message

프로그램은 인쇄 할 수없는 문자를 포함 할 수있는 암호화 된 문자열을 출력합니다. CipherSaber Encryption & Decryption Tool을 사용하여이를 검증 하려면 다음 코드를 사용하여 문자열을 일련의 16 진 숫자로 변환 할 수 있습니다.

$import os$KsM$os.urandom(10)$JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256=Z0         
jdm.[2.HCd`0
sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

Pyth는 암호로 안전한 의사 난수를 지원하지 않으며 Python에서 가져 오는 데 25 바이트가 소요됩니다. Pyth / Python의 normar pseudorandom-number generator를 사용하고 온라인 컴파일러에서도 작동하는 짧은 코드는 다음과 같습니다.

KmO=b256TJuuXN@LN,T=+Z+@NT@+CMzKT)bGQUb=Z0sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

온라인으로 시도 : 문자열 또는 일련의 16 진수를 반환

코드는 특별한 것이 아닙니다. 더티 할당 및 계산 된 결과의 즉각적인 재사용과 목록 스왑 트릭의 두 배 적용 .

설명:

                                  implicit: z = 1st input (= key string)
                                  Q = 2nd input (number of repetitions)
$import os$KsM$os.urandom(10)$
$import os$                       import Python's os module
              $os.urandom(10)$    create 10 cryptographically secure 
                                  pseudo-random bytes
            sM                    convert them to ints
           K                      store them in K

JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256
                             =b256assign b with 256
 u                         QUb    start with G = [0, 1, ..., 255], 
                                  evaluate the following expression Q times and
                                  update G with the result each time:
  u                      bG         start with N = G, 
                                    for each T in [0, 1, ..., 255] evaluate the
                                    following expression and update N each time:
                   CMz                convert key to list of ints
                  +   K               extend it with K
                 @     T              take the Tth element (modulo length)
              @NT                     take the Tth element of N
             +                        add these two values
           +Z                         add Z (with is initially 0)
          =                           and update Z with the result
        ,T  Z                         make the pair of indices [T, Z] 
     @LN                              look-up their values in N
   XN                   )             and switch these two values in N
J                                 assign the result (the key setup) to J

=Z0                               set Z to 0

sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw 
                                w read a string from input (message)
     .e                           map each index k, char b in message to:
                         @Jhk       look-up the (k+1)th element in J
                      =+Z           add it to Z and update Z
                   ,hk  Z           make the pair of indices [k+1,Z]
                @LJ                 look-up their values in J
              =N                    assign the result to N
            XJ N             )      swap these values in J
           =                        and update J with the result
          @  J                sN    take the sum(N)th element of J
        Cb                          convert b to int
       x                            bitwise xor of these two elements
   +K                             insert K at the beginning
 CM                               convert each element to char
s                                 sum them (generate a string)
                                  implicitly print

분명히 내장 Pyth 함수에는 암호로 안전한 의사 난수 숫자가 없습니다 . 출품작을 그대로 유지할 수 있으며 녹색 진드기에 해당하지 않거나 urandom"승리"에 관심이있는 경우 원하는 경우 별도의 출품작 이 될 수있는 버전을 만들 수 있습니다. :-)
Chris Jester-Young

@ ChrisJester-Young 미안합니다. 파이썬의 난수 생성기가 안전하지 않다고 생각했습니다. 25 바이트의 비용으로 수정했습니다.
Jakube

4

파이썬 2 - (373) 350 326 317 바이트

Pyth는 나중에 올 것입니다. c(p,d,r,m)암호문 및 데이터에 대한 바이트 목록을 사용하고 1 일 때 암호화하고 0 일 때 해독하는 반복 및 모드에 대해 int를 사용하는 하나의 함수를 정의합니다 . 이는 IV와의 유일한 차이점이기 때문입니다. 바이트리스트를 돌려줍니다.

import os
B=256
def c(p,d,r,m):
    if m:v=map(ord,os.urandom(10))
    else:v,d=d[:10],d[10:]
    p+=v;S=range(B);T=(p*B)[:B];j=0;exec"for i in range(B):j=(j+S[i]+T[i])%B;S[i],S[j]=S[j],S[i]\n"*r;o=[];i=j=0
    for b in d:i=-~i%B;j=(j+S[i])%B;S[i],S[j]=S[j],S[i];k=(S[i]+S[j])%B;o+=[S[k]^b]
    return v+o if m else o

다음은 몇 가지 테스트 코드 / 도우미 기능입니다.

phrase = "hello"
text = "Mary had a little lamb, little lamb, little lamb"
N = 5

def make_bytes(string):
    return map(ord, string)

def make_string(bytes):
    return "".join(map(chr, bytes))

def make_hex(bytes):
    return " ".join("%02x" % i for i in bytes)

def from_hex(hex_str):
    return [int(i, 16) for i in hex_str.split()]

cipher = c(make_bytes(phrase), make_bytes(text), N, 1)
print make_hex(cipher)
plain = c(make_bytes(phrase), cipher, N, 0)
print make_string(plain)

암호화 프로그램 만 작성하면됩니다. 따라서 else:v,d=d[:10],d[10:]부품을 제거 할 수 있습니다 .
Jakube

3

루비-263 자

이것은 2010 년의 stackoverflow에 관한 원래 질문에 대한 Ruby 답변입니다! 하나의 프로그램에서 모두 인코더 및 디코더입니다.

매개 변수는 다음과 같습니다.
e 또는 d (인코딩 또는 디코딩 용)

횟수

$ ruby saber.rb e gnibbler 10 < in.txt | ruby saber.rb d gnibbler 10

o,k,l=ARGV;print o<'e'?(v=STDIN.read(10))*0:v=(0..9).map{rand(256).chr}.join;j=0;E=255
S=Array 0..255;(S*l.to_i).each{|i|j=j+S[i]+((k+v)*E)[i].ord&E;S[i],S[j]=S[j],S[i]};i=j=0
STDIN.each_byte{|c|i=i+1&E;j=j+S[i]&E;S[i],S[j]=S[j],S[i];print (c^S[S[i]+S[j]&E]).chr}

2

C, 312 바이트

명령 행에서 키 및 키 믹싱 반복 횟수를 승인 한 후 stdin의 모든 항목을 stdout으로 암호화합니다. arc4random()RC4 기반의 PRNG 인 BSD / Darwin 라이브러리 함수를 사용합니다 . 자동으로 시드되므로 결과는 매번 달라집니다.

unsigned char n,i,j,q,x,t,s[256],k[256];main(int c,char**v){for(strcpy(k,v[1]),n=strlen(k);x<10;x++)putchar(k[n++]=arc4random());do{s[i]=i;}while(++i);for(x=atoi(v[2]);x--;)do{t=s[i];s[i]=s[j+=s[i]+k[i%n]];s[j]=t;}while(++i);for(;(c=getchar())>0;){q+=s[++i];t=s[i];s[i]=s[q];s[q]=t;t=s[i]+s[q];putchar(c^s[t]);}}

Tidier 버전 :

unsigned char n,i,j,q,x,t,s[256],k[256];
main(int c,char**v) {
  for (strcpy(k,v[1]),n=strlen(k);x<10;x++) putchar(k[n++]=arc4random());
  do {
    s[i]=i;
  }
  while(++i);
  for (x=atoi(v[2]);x--;) do {
    t=s[i];
    s[i]=s[j+=s[i]+k[i%n]];
    s[j]=t;
  }
  while (++i);
  for (;(c=getchar())>0;) {
    q+=s[++i];
    t=s[i];
    s[i]=s[q];
    s[q]=t;
    t=s[i]+s[q];
    putchar(c^s[t]);
  }
}

예:

$ echo -n 'Ciphersaber' | ./csgolf 'hello' 20 | xxd -p
0f6257c330e5e01c3eab07bc9cb4ee4c3eaa514a85

1

파이썬-266 자

이것은 2010 년의 stackoverflow에 관한 원래 질문에 대한 Python 답변입니다! 하나의 프로그램에서 모두 인코더 및 디코더입니다.

매개 변수는 다음과 같습니다.
e 또는 d (인코딩 또는 디코딩 용)

횟수

$ python saber.py e gnibbler 10 < in.txt | python saber.py d gnibbler 10

이 버전은 rc4의 2 개의 루프를 하나로 병합하려고합니다 (11 바이트는 지금까지 저장).

import os,sys;X,Y=sys.stdin.read,os.write;_,o,k,l=sys.argv;p='d'<o
V=(X,os.urandom)[p](10);Y(1,V*p);E,S=255,range(256)
for q in S*int(l),X():
 t=q<'';j=0;i=-t
 for c in q:i=i+1&E;j=j+S[i]+t*ord(((k+V)*E)[i])&E;S[i],S[j]=S[j],S[i];t or Y(1,chr(ord(c)^S[S[i]+S[j]&E]))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.