Mã hóa đơn giản cho những người có ngân sách byte


17

Tổng quat

Mục tiêu của bạn là thực hiện mã hóa RC4. Mã hóa RC4, được phát minh bởi Ron Rivest (danh tiếng RSA), được thiết kế để bảo mật, nhưng đủ đơn giản để được thực hiện từ bộ nhớ của các binh sĩ quân đội trên chiến trường. Ngày nay, có một số cuộc tấn công vào RC4, nhưng nó vẫn được sử dụng ở nhiều nơi ngày nay.

Chương trình của bạn nên chấp nhận một chuỗi có cả khóa và một số dữ liệu. Nó sẽ được trình bày trong định dạng này.

\x0Dthis is a keythis is some data to encrypt

Byte đầu tiên biểu thị thời gian của khóa là bao lâu. Có thể giả sử khóa sẽ không dài hơn 255 byte và không ngắn hơn 1 byte. Các dữ liệu có thể dài tùy ý.

Chương trình của bạn nên xử lý khóa, sau đó trả lại dữ liệu được mã hóa. Mã hóa và giải mã RC4 là giống hệt nhau, vì vậy sử dụng cùng một khóa để "mã hóa" bản mã sẽ trả về bản gốc.

RC4 hoạt động như thế nào

Khởi tạo

Khởi tạo RC4 khá đơn giản. Một mảng trạng thái 256 byte được khởi tạo cho tất cả các byte từ 0 đến 255.

S = [0, 1, 2, 3, ..., 253, 254, 255]

Xử lý khóa

Các giá trị trong trạng thái được hoán đổi dựa trên khóa.

j = 0
for i from 0 to 255
    j = (j + S[i] + key[i mod keylength]) mod 256
    swap S[i] and S[j]

Mã hóa

Mã hóa được thực hiện bằng cách sử dụng trạng thái để tạo các byte giả ngẫu nhiên, sau đó là XOR cho dữ liệu. Các giá trị trong tiểu bang được hoán đổi liên tục.

i = j = 0
for each byte B in data
    i = (i + 1) mod 256
    j = (j + S[i]) mod 256
    swap S[i] and S[j]
    K = S[(S[i] + S[j]) mod 256]
    output K XOR B

Dự kiến ​​đầu vào và đầu ra

Các ký tự không in được sẽ được hiển thị ở \xABđịnh dạng.

Đầu vào: \x01\x00\x00\x00\x00\x00\x00
Đầu ra: \xde\x18\x89A\xa3
Đầu ra (hex):de188941a3

Đầu vào: \x0Dthis is a keythis is some data to encrypt
Đầu ra: \xb5\xdb?i\x1f\x92\x96\x96e!\xf3\xae(!\xf3\xeaC\xd4\x9fS\xbd?d\x82\x84{\xcdN
Đầu ra (hex):b5db3f691f9296966521f3ae2821f3ea43d49f53bd3f6482847bcd4e

Đầu vào: \x0dthis is a key\xb5\xdb?i\x1f\x92\x96\x96e!\xf3\xae(!\xf3\xeaC\xd4\x9fS\xbd?d\x82\x84{\xcdN
Đầu vào (hex): 0d746869732069732061206b6579b5db3f691f9296966521f3ae2821f3ea43d49f53bd3f6482847bcd4e
Đầu ra:this is some data to encrypt

Đầu vào: Sthis is a rather long key because the value of S is 83 so the key length must matchand this is the data to be encrypted
Đầu ra: \x96\x1f,\x8f\xa3%\x9b\xa3f[mk\xdf\xbc\xac\x8b\x8e\xfa\xfe\x96B=!\xfc;\x13`c\x16q\x04\x11\xd8\x86\xee\x07
Đầu ra (hex):961f2c8fa3259ba3665b6d6bdfbcac8b8efafe96423d21fc3b13606316710411d886ee07


Bạn muốn chọn chế độ đầu ra nào, hoặc chúng ta có thể chọn chế độ nào? Hex sẽ được ưu tiên
andrewarchi

@andrewarchi Đầu ra được cho là tính bằng byte để có thể quay vòng qua để giải mã.
Daffy

1
Chúng ta cũng có thể lấy đầu vào là một mảng byte?
Arnauld

1
@andrewarchi Những ký hiệu đó chỉ để đọc. Nếu chương trình của bạn được cho là xuất ra \xde, thì nó phải dài 1 byte và chuyển đổi nó thành một số (thông qua python's ord()hoặc javascript .charCodeAt(0)) sẽ trả về 222 (0xDE).
Daffy

1
@Arnauld Xem xét hai về cơ bản là không thể phân biệt được trong rất nhiều ngôn ngữ, vâng.
Daffy

Câu trả lời:


3

JavaScript (ES6), 169 168 byte

Lấy đầu vào là một mảng byte. Trả về một mảng byte khác.

([l,...s])=>s.slice(l).map(b=>b^S[(S[S[J=J+(t=S[I=I+1&m])&m,I]=x=S[J],J]=t)+x&m],[...S=[...Array(m=255).keys(),m]].map(i=>S[S[i]=S[j=j+(t=S[i])+s[i%l]&m],j]=t,I=J=j=0))

Làm sao?

Đây thực chất là một triển khai theo nghĩa đen của thông số kỹ thuật.

Trước tiên chúng tôi chia mảng đầu vào thành l (chiều dài của khóa) và s (dữ liệu tải trọng: khóa + thông báo). Sau đó, theo thứ tự thực hiện:

  • Chúng tôi khởi tạo mảng trạng thái S và xác định m = 255 được sử dụng nhiều lần sau đó dưới dạng mặt nạ bit.

    S = [...Array(m = 255).keys(), m]
  • Chúng tôi xáo trộn các mảng nhà nước. Các chỉ số I J được khởi tạo ở đây thực sự được sử dụng trong bước tiếp theo.

    [...S].map(i =>
      S[S[i] = S[j = j + (t = S[i]) + s[i % l] & m], j] = t,
      I = J = j = 0
    )
  • Chúng tôi áp dụng mã hóa.

    s.slice(l).map(b =>
      b ^ S[
        (S[S[J = J + (t = S[I = I + 1 & m]) & m, I] = x = S[J], J] = t) +
        x & m
      ]
    )
    

Các trường hợp thử nghiệm


13

138 byte, mã máy (16 bit x86)

000000 88 9f 00 02 fe c3 75 f8 b9 01 00 89 fa b4 3f cd
000010 21 86 0d ba 00 03 b4 3f cd 21 89 dd 01 f6 02 9e
000020 00 03 8a 04 00 c3 86 87 00 02 88 04 46 45 39 cd
000030 75 02 31 ed 81 fe 00 03 75 e4 81 ee 00 01 31 db
000040 31 d2 ff c6 81 fe 00 03 75 04 81 ee 00 01 8a 04
000050 00 c3 88 c2 86 87 00 02 88 04 00 c2 89 d7 81 c7
000060 00 02 8a 15 89 d7 89 dd 31 db ba 00 03 b9 01 00
000070 b8 00 3f cd 21 87 fa 30 15 85 c0 74 0b 87 fa 43
000080 b4 40 cd 21 89 eb eb b8 cd 20

Đang chạy: lưu vào codegolf.com, dosbox:

codegolf.com < input.bin

nỗ lực thành công

Tôi không biết nếu điều này sẽ được tính là một mục, nhưng tôi đã quyết định làm nó bằng tay sử dụng các trình soạn thảo hex. Không có trình biên dịch đã được sử dụng để làm điều này.

Trình soạn thảo ht thực sự có trình biên dịch chương trình, nhưng thật lòng tôi không biết về điều này cho đến khi tôi hoàn thành ¯ \ _ (ツ) _ /

Sao lại như vậy

Tại sao: chủ yếu là vì tôi muốn kiểm tra xem tôi có thể làm điều này không.

Cách thực hiện: Tôi đã bắt đầu với việc tạo byte chứa đầy NOPs và làm theo một phần đơn giản: cố gắng viết vòng lặp đầu tiên lấp đầyS tate với các giá trị 0..255. Tôi chuyển sang python và nhanh chóng viết phiên bản python, chỉ để có cái gì đó để kiểm tra. Tiếp theo tôi đã đơn giản hóa mã python thành mã giả / lắp ráp giả. Sau đó, II đã cố gắng viết những mẩu nhỏ. Tôi quyết định sẽ dễ đọc nhất từ ​​stdin, vì vậy tôi bắt đầu với một cái gì đó nhỏ sẽ đọc một byte, sau đó tôi thêm đọc mật khẩu và khởi tạo khóa. Tìm ra những gì đăng ký để chọn mất một thời gian.

Tôi mặc dù việc thêm vòng lặp mã hóa sẽ dễ dàng, nhưng trước tiên tôi thực sự có được giải mã byte đơn và thêm toàn bộ vòng lặp sau đó.

Bước cuối cùng là loại bỏ bổ sung nopsmà tôi đã để lại giữa các hướng dẫn khi viết nó (cũng cần phải sửa lỗi nhảy).

Bạn có thể thấy bộ sưu tập nhỏ mà tôi đã cố gắng thực hiện trong khi tiến hành ở đây .

Mổ xẻ

Chương trình dựa trên một số giá trị ban đầu sau khi khởi động (xem tài nguyên bên dưới).

00000000 889f0002                  mov         [bx+0200], bl
00000004 fec3                      inc         bl
00000006 75f8                      jnz         0x0

điền vào tiểu bang (tại 0x200)

00000008 b90100                    mov         cx, 0x1
0000000b 89fa                      mov         dx, di
0000000d b43f                      mov         ah, 0x3f
0000000f cd21                      int         0x21
00000011 860d                      xchg        [di], cl
00000013 ba0003                    mov         dx, 0300
00000016 b43f                      mov         ah, 0x3f
00000018 cd21                      int         0x21

đọc độ dài, đọc mật khẩu, lưu trữ mật khẩu tại DS: 0x300

0000001a 89dd                      mov         bp, bx
0000001c 01f6                      add         si, si
0000001e 029e0003                  add         bl, [bp+0300]
00000022 8a04                      mov         al, [si]
00000024 00c3                      add         bl, al
00000026 86870002                  xchg        [bx+0200], al
0000002a 8804                      mov         [si], al
0000002c 46                        inc         si
0000002d 45                        inc         bp
0000002e 39cd                      cmp         bp, cx
00000030 7502                      jnz         0x34
00000032 31ed                      xor         bp, bp
00000034 81fe0003                  cmp         si, 0300
00000038 75e4                      jnz         0x1e

khởi tạo Trạng thái bằng một khóa ( BPđược sử dụng để duyệt ngang, SIđược sử dụng để duyệt trạng thái)

0000003a 81ee0001                  sub         si, 0100
0000003e 31db                      xor         bx, bx
00000040 31d2                      xor         dx, dx
00000042 ffc6                      inc         si
00000044 81fe0003                  cmp         si, 0300
00000048 7504                      jnz         0x4e
0000004a 81ee0001                  sub         si, 0100
0000004e 8a04                      mov         al, [si]
00000050 00c3                      add         bl, al
00000052 88c2                      mov         dl, al
00000054 86870002                  xchg        [bx+0200], al
00000058 8804                      mov         [si], al
0000005a 00c2                      add         dl, al
0000005c 89d7                      mov         di, dx
0000005e 81c70002                  add         di, 0200
00000062 8a15                      mov         dl, [di]

tạo giá trị giả ngẫu nhiên (trong DL, DHlà 0 thx đến xor tại 0x140)

00000064 89d7                      mov         di, dx      
00000066 89dd                      mov         bp, bx      
00000068 31db                      xor         bx, bx      
0000006a ba0003                    mov         dx, 0300    
0000006d b90100                    mov         cx, 0x1     
00000070 b8003f                    mov         ax, 3f00    
00000073 cd21                      int         0x21        
00000075 87fa                      xchg        dx, di      
00000077 3015                      xor         [di], dl    
00000079 85c0                      test        ax, ax      
0000007b 740b                      jz          0x88        
0000007d 87fa                      xchg        dx, di      
0000007f 43                        inc         bx          
00000080 b440                      mov         ah, 0x40    
00000082 cd21                      int         0x21        
00000084 89eb                      mov         bx, bp      
00000086 ebb8                      jmp         0x40        
00000088 cd20                      int         0x20        
  • lưu trữ các giá trị mà chúng ta cần bảo tồn ( SI- ints sẽ không chạm vào nó, BX)
  • đọc char từ đầu vào, xor nó
  • thoát nếu kết thúc luồng
  • đầu ra được giải mã char
  • khôi phục giá trị
  • lặp đến 0x40 (sử dụng lại xor trên DX)

PS Điều này có thể thậm chí còn ngắn hơn, nhưng điều này mất 4 buổi tối, vì vậy tôi không chắc liệu tôi có muốn chi tiêu khác không ...

Công cụ và tài nguyên


4

C (gcc) , 193 188 182 178 171 172 byte

f(x,l)int*x;{unsigned char*X=x,i=0,j=0,S[256],t;for(;S[i]=++i;);for(;t=S[i],S[i]=S[j+=t+X[1+i%*X]],S[j]=t,t=++i;);for(X+=*X;l--;S[i]-=S[t]=j)*++X^=S[S[i]+=S[t+=j=S[++i]]];}

Hãy thử trực tuyến!

Chỉnh sửa: Bây giờ hoạt động với các khóa dài hơn 127 byte.

Edit2: Đã thêm testcase với khóa 129 byte vào liên kết TIO.

Phiên bản ít chơi gôn hơn

f(x,l)int*x;{
  unsigned char*X=x,i=0,j=0,S[256],t;
  // initialize state
  for(;S[i]=++i;);
  // key processing
  for(;t=S[i],S[i]=S[j+=t+X[1+i%*X]],S[j]=t,t=++i;);
  // encrypt
  for(X+=*X;l--;S[i]-=S[t]=j)
    *++X^=S[S[i]+=S[t+=j=S[++i]]];
}

Bạn không sợ lỗi của trình biên dịch C chung? Đó là hành vi không xác định s [i] = ++ i? Có tôi biết có thể nó chỉ quan trọng với trình biên dịch mà một người sử dụng ...
RosLuP

Đối với những gì nó được viết trong khóa phần "Xử lý khóa" phải là <= 256 byte ... (vì các ký tự khác không ảnh hưởng đến tính toán và hoán đổi)
RosLuP

Và tại sao sẽ không ổn khi sử dụng char * thay vì int * trong đối số (có chỉ ít ký tự)? Tôi có vẻ ổn ngay cả đối với khóa có độ dài 129 byte ... Có vẻ như hành vi không xác định
RosLuP

4

Tập lệnh CPU x86, 133 byte

000009F8  53                push ebx
000009F9  56                push esi
000009FA  57                push edi
000009FB  55                push ebp
000009FC  55                push ebp
000009FD  BF00010000        mov edi,0x100
00000A02  29FC              sub esp,edi
00000A04  8B6C3C18          mov ebp,[esp+edi+0x18]
00000A08  31DB              xor ebx,ebx
00000A0A  8A5D00            mov bl,[ebp+0x0]
00000A0D  45                inc ebp
00000A0E  31C0              xor eax,eax
00000A10  880404            mov [esp+eax],al
00000A13  40                inc eax
00000A14  39F8              cmp eax,edi
00000A16  72F8              jc 0xa10
00000A18  31F6              xor esi,esi
00000A1A  31C9              xor ecx,ecx
00000A1C  89F0              mov eax,esi
00000A1E  31D2              xor edx,edx
00000A20  F7F3              div ebx
00000A22  8A0434            mov al,[esp+esi]
00000A25  02441500          add al,[ebp+edx+0x0]
00000A29  00C1              add cl,al
00000A2B  8A0434            mov al,[esp+esi]
00000A2E  8A140C            mov dl,[esp+ecx]
00000A31  88040C            mov [esp+ecx],al
00000A34  881434            mov [esp+esi],dl
00000A37  46                inc esi
00000A38  39FE              cmp esi,edi
00000A3A  72E0              jc 0xa1c
00000A3C  8B443C1C          mov eax,[esp+edi+0x1c]
00000A40  01E8              add eax,ebp
00000A42  722F              jc 0xa73
00000A44  48                dec eax
00000A45  89C6              mov esi,eax
00000A47  01DD              add ebp,ebx
00000A49  31C0              xor eax,eax
00000A4B  31D2              xor edx,edx
00000A4D  31C9              xor ecx,ecx
00000A4F  39F5              cmp ebp,esi
00000A51  7320              jnc 0xa73
00000A53  FEC2              inc dl
00000A55  8A0414            mov al,[esp+edx]
00000A58  00C1              add cl,al
00000A5A  8A1C0C            mov bl,[esp+ecx]
00000A5D  88040C            mov [esp+ecx],al
00000A60  881C14            mov [esp+edx],bl
00000A63  00D8              add al,bl
00000A65  8A1C04            mov bl,[esp+eax]
00000A68  8A4500            mov al,[ebp+0x0]
00000A6B  30D8              xor al,bl
00000A6D  884500            mov [ebp+0x0],al
00000A70  45                inc ebp
00000A71  EBDC              jmp short 0xa4f
00000A73  01FC              add esp,edi
00000A75  5D                pop ebp
00000A76  5D                pop ebp
00000A77  5F                pop edi
00000A78  5E                pop esi
00000A79  5B                pop ebx
00000A7A  C20800            ret 0x8
00000A7D

A7D-9F8 = 85h = 133 byte nhưng tôi không biết tính toán có ổn không vì số byte trước của cùng một hàm có kết quả 130 byte ... Đối số đầu tiên của hàm mà tôi đặt tên là "cript" là chuỗi, đối số thứ hai là chiều dài chuỗi (byte đầu tiên + chiều dài khóa + chiều dài thông điệp). Dưới đây là tệp ngôn ngữ lắp ráp để có được các thói quen cript đó:

; nasmw -fobj  this.asm

section _DATA use32 public class=DATA
global cript
section _TEXT use32 public class=CODE

cript:    
      push    ebx
      push    esi
      push    edi
      push    ebp
      push    ebp
      mov     edi,  256
      sub     esp,  edi
      mov     ebp,  dword[esp+  edi+24]
      xor     ebx,  ebx
      mov     bl,  [ebp]
      inc     ebp
      xor     eax,  eax
.1:   mov     [esp+eax],  al
      inc     eax
      cmp     eax,  edi
      jb      .1
      xor     esi,  esi
      xor     ecx,  ecx
.2:   mov     eax,  esi
      xor     edx,  edx
      div     ebx
      mov     al,  [esp+esi]
      add     al,  [ebp+edx]
      add     cl,  al
      mov     al,  [esp+esi]
      mov     dl,  [esp+ecx]
      mov     [esp+ecx],  al
      mov     [esp+esi],  dl
      inc     esi
      cmp     esi,  edi
      jb      .2
      mov     eax,  dword[esp+  edi+28]
      add     eax,  ebp
      jc      .z
      dec     eax
      mov     esi,  eax
      add     ebp,  ebx
      xor     eax,  eax
      xor     edx,  edx
      xor     ecx,  ecx
.3:   cmp     ebp,  esi
      jae     .z
      inc     dl
      mov     al,  [esp+edx]
      add     cl,  al
      mov     bl,  [esp+ecx]
      mov     [esp+ecx],  al
      mov     [esp+edx],  bl ; swap S[c] S[r]
      add     al,  bl
      mov     bl,  [esp+eax]
      mov     al,  [ebp]
      xor     al,  bl
      mov     [ebp],  al
      inc     ebp
      jmp     short  .3
.z:       
      add     esp,  edi
      pop     ebp
      pop     ebp
      pop     edi
      pop     esi
      pop     ebx
      ret     8

bên dưới tệp C để kiểm tra kết quả:

// Nasmw  -fobj  fileasm.asm
// bcc32 -v filec.c fileasm.obj
#include <stdio.h>

void _stdcall cript(char*,unsigned);

char es1[]="\x01\x00\x00\x00\x00\x00\x00";
char es2[]="\x0Dthis is a keythis is some data to encrypt";
char es3[]="\x0dthis is a key\xb5\xdb?i\x1f\x92\x96\226e!\xf3\xae(!\xf3\xea\x43\xd4\x9fS\xbd?d\x82\x84{\xcdN";
char es4[]="Sthis is a rather long key because the value of S is 83 so the key length must matchand this is the data to be encrypted";

void printMSGKeyC(unsigned char* a, unsigned len)
{unsigned i,j,k;
 unsigned char *p,*end;

 printf("keylen = %u\nKey    = [", (unsigned)*a);
 for(i=1, j=*a;i<=j;++i) printf("%c", a[i]);
 printf("]\nMessage= [");
 for(p=a+i,end=a+len-1;p<end;++p)printf("%c", *p);
 printf("]\n");
}

void printMSGKeyHex(unsigned  char* a, unsigned len)
{unsigned i,j,k;
 unsigned char *p,*end;

 printf("keylen = %u\nKey    = [", (unsigned)*a);
 for(i=1, j=*a;i<=j;++i) printf("%02x", a[i]);
 printf("]\nMessage= [");
 for(p=a+i,end=a+len-1;p<end;++p)printf("%02x", *p);
 printf("]\n");
}


main()
{printf("sizeof \"%s\"= %u [so the last byte 0 is in the count]\n", "this", sizeof "this");

 printf("Input:\n");
 printMSGKeyHex(es1, sizeof es1);
 cript(es1,  (sizeof es1)-1);
 printf("Afther I cript:\n");
 printMSGKeyHex(es1, sizeof es1);

 printf("Input:\n");
 printMSGKeyC(es2, sizeof es2);
 printMSGKeyHex(es2, sizeof es2);
 cript(es2,  (sizeof es2)-1);
 printf("Afther I cript:\n");
 printMSGKeyC(es2, sizeof es2);
 printMSGKeyHex(es2, sizeof es2);
 cript(es2,  (sizeof es2)-1);
 printf("Afther II cript:\n");
 printMSGKeyC(es2, sizeof es2);
 printMSGKeyHex(es2, sizeof es2);
 printf("----------------------\n");

 printf("Input:\n");
 printMSGKeyHex(es3, sizeof es3);
 cript(es3,  (sizeof es3)-1);
 printf("Afther I cript:\n");
 printMSGKeyHex(es3, sizeof es3);
 printf("----------------------\n");

 printf("Input:\n");
 printMSGKeyHex(es4, sizeof es4);
 cript(es4,  (sizeof es4)-1);
 printf("Afther I cript:\n");
 printMSGKeyHex(es4, sizeof es4);
 cript(es4,  (sizeof es4)-1);
 printf("Afther II cript:\n");
 printMSGKeyHex(es4, sizeof es4);

 return 0;
}

kết quả:

 sizeof "this"= 5 [so the last byte 0 is in the count]
Input:
keylen = 1
Key    = [00]
Message= [0000000000]
Afther I cript:
keylen = 1
Key    = [00]
Message= [de188941a3]
Input:
keylen = 13
Key    = [this is a key]
Message= [this is some data to encrypt]
keylen = 13
Key    = [746869732069732061206b6579]
Message= [7468697320697320736f6d65206461746120746f20656e6372797074]
Afther I cript:
keylen = 13
Key    = [this is a key]
Message= [Á█?iÆûûe!¾«(!¾ÛCȃS¢?déä{═N]
keylen = 13
Key    = [746869732069732061206b6579]
Message= [b5db3f691f9296966521f3ae2821f3ea43d49f53bd3f6482847bcd4e]
Afther II cript:
keylen = 13
Key    = [this is a key]
Message= [this is some data to encrypt]
keylen = 13
Key    = [746869732069732061206b6579]
Message= [7468697320697320736f6d65206461746120746f20656e6372797074]
----------------------
Input:
keylen = 13
Key    = [746869732069732061206b6579]
Message= [b5db3f691f9296966521f3ae2821f3ea43d49f53bd3f6482847bcd4e]
Afther I cript:
keylen = 13
Key    = [746869732069732061206b6579]
Message= [7468697320697320736f6d65206461746120746f20656e6372797074]
----------------------
Input:
keylen = 83
Key    = [74686973206973206120726174686572206c6f6e67206b65792062656361757365207468652076616c7565206f66205320697320383320736f20746865206b6579206c656e677468206d757374206d61746368]
Message= [616e64207468697320697320746865206461746120746f20626520656e63727970746564]
Afther I cript:
keylen = 83
Key    = [74686973206973206120726174686572206c6f6e67206b65792062656361757365207468652076616c7565206f66205320697320383320736f20746865206b6579206c656e677468206d757374206d61746368]
Message= [961f2c8fa3259ba3665b6d6bdfbcac8b8efafe96423d21fc3b13606316710411d886ee07]
Afther II cript:
keylen = 83
Key    = [74686973206973206120726174686572206c6f6e67206b65792062656361757365207468652076616c7565206f66205320697320383320736f20746865206b6579206c656e677468206d757374206d61746368]
Message= [616e64207468697320697320746865206461746120746f20626520656e63727970746564]

3

JavaScript (ES6), 262 byte

Tôi đã cân nhắc việc chỉ sử dụng các hàm bị xiềng xích, nhưng đã chọn tham gia đánh gôn thuật toán được đưa ra ở đây: https://gist.github.com/farhadi/2185197 .

A=>eval(`for(C=A[c='charCodeAt']
(),K=A.slice(1,++C),T=A.slice(C),i=j=k=l=m=y=0,s=[],r=[],a=256;i<a;)s[i]=i++
for(;j<a;){t=s[k=(k+s[j]+K[c](j%K.length))%a]
s[k]=s[j]
s[j++]=t}for(;y<T.length;){r[y]=T[c](y++)^s[((t=s[m=(m+s[l=++l%a])%a])+
(s[m]=s[l]))%a]
s[l]=t}r`)

Ít chơi gôn

A=>{
  C=A.charCodeAt()
  K=A.slice(1,++C)
  T=A.slice(C)
  for(i=j=k=l=m=y=0,s=[],r=[];i<256;)s[i]=i++
  for(;j<256;){
    t=s[k=(k+s[j]+K.charCodeAt(j%K.length))%256];
    s[k]=s[j];
    s[j++]=t;
  }
  for(;y<T.length;){
    t=s[m=(m+s[l=(l+1)%256])%256];
    s[m]=s[l];
    s[l]=t;
    r[y]=T.charCodeAt(y++)^s[(s[l]+s[m])%256];
  }
  return r;
}


2
+1 Tôi luôn đánh giá cao điều đó khi mọi người đưa ra những lời giải thích cho mã golf.
Daffy

2

Python 2 , 203 byte

def f(x):
	def h():S[i],S[j]=S[j],S[i]
	m=256;x=map(ord,x);S=range(m);l=x.pop(0);j=0
	for i in S[:]:j=(j+S[i]+x[i%l])%m;h()
	i=j=0
	for b in x[l:]:i=(i+1)%m;j=(j+S[i])%m;h();yield chr(S[(S[i]+S[j])%m]^b)

Hãy thử trực tuyến!

f là một bộ tạo (lặp) của chuỗi.

Ung dung:

def f(x):
    def h():
        S[i], S[j] = S[j], S[i]  # we have to do this two times
    m = 256  # used often
    x = map(ord, x)  # get numbers to do stuff with
    S = range(m)  # init State
    l = x.pop(0)  # get key length and remove the first byte in one go
    j = 0
    for i in S[:]:  # shorter than range(256)
        j = (j + S[i] + x[i%l]) % m
        h()
    i = j = 0
    for b in x[l:]:  # data comes after the key
        i = (i+1) % m
        j = (j+S[i]) % m
        h()
        yield chr(S[(S[i]+S[j]) % m] ^ b)  # convert to str again

1

Ruby, 234 byte

Chưa được kiểm tra.

->s{l=s[0].ord;k=s[1..l];i=s[l+1..-1];o='';s=[*0..255];i,j,q=0;256.times{|i|j=(j+s[i]+k[i%k.size].ord)%256;s[i],s[j]=s[j],s[i]};i.size.times{|k|i=(i+1)%256;q=(q+s[i])%256;s[i],s[q]=s[q],s[i];b=s[(s[i]+s[q])%256];o<<(b^i[k].ord).chr;o}

1

C, 181 byte

f(a,n)char*a;{unsigned char A=*a++,i=-1,j=0,k,s[256];for(;s[i]=i;--i);for(;k=s[i],s[i]=s[j+=k+a[i%A]],s[j]=k,k=++i;);for(n-=A,a+=A;--n;*a++^=s[j+=A])j=s[++i],A=s[i]=s[k+=j],s[k]=j;}

nhờ trần nhà cho một số byte ít hơn:

f(a,n)char*a;
{unsigned char A=*a++,i=-1,j=0,k,s[256];
 for(;s[i]=i;--i);
 for(;k=s[i],s[i]=s[j+=k+a[i%A]],s[j]=k,k=++i;);
 for(n-=A,a+=A;--n;*a++^=s[j+=A])j=s[++i],A=s[i]=s[k+=j],s[k]=j;
}

f (a, n) trong "a" sẽ có mảng ký tự 1Byte len + key + message; trong n có kích thước của tất cả mảng "a" không được tính '\ 0' cuối cùng. mã để kiểm tra và kết quả sẽ là mã được sử dụng cho chức năng lắp ráp.


@ceilingcat đối số của tôi về hàm n, ở đây là độ dài của tất cả các mảng ký tự (1byte + key + message) ... độ dài của tin nhắn phải là: nk-1 trong đó k là độ dài của khóa và n là độ dài của tất cả các mảng ký tự.
RosLuP

@ceilingcat cho tôi cuộc gọi "f (a, sizeof a);" là sai vì sizeof tính theo độ dài của 'a' char được nối thêm '\ 0' ở cuối chuỗi ... Vì vậy, nó phải là f (a, (sizeof a) -1)
RosLuP

Tôi không đồng ý trong điều này ", * ++ a ^ = s [j + = s [i]])" đối với tôi, ở đây nó đọc 2 lần cho mảng và trong một hướng dẫn tương tự khác ở đây, kết quả lại khác. ..
RosLuP

1

APL (NARS), 329 ký tự, 658 byte

xor←{⍺<0:¯1⋄⍵<0:¯1⋄⍺=0:⍵⋄⍵=0:⍺⋄k←⌈/{⌊1+2⍟⍵}¨⍺⍵⋄(2⍴⍨≢m)⊥m←↑≠/{(k⍴2)⊤⍵}¨⍺⍵}
∇r←C w;s;i;j;l;t;b;x
k←256⋄s←¯1+⍳k⋄i←j←0⋄l←¯1+⎕AV⍳↑w
t←s[1+i]⋄j←k∣¯1+j+t+⎕AV⍳w[2+l∣i]⋄s[1+i]←s[1+j]⋄s[1+j]←t⋄i+←1⋄→2×⍳i<k
i←j←0⋄b←≢w⋄l+←1
l+←1⋄→6×⍳l>b⋄i←k∣i+1⋄t←s[1+i]⋄j←k∣j+t⋄s[1+i]←s[1+j]⋄s[1+j]←t
x←s[1+k∣t+s[1+i]] xor ¯1+⎕AV⍳w[l]⋄w[l]←⎕AV[1+x]⋄→4
r←w
∇

như mọi khi kiểm tra lỗi sẽ được yêu cầu cho người khác ... Điều này có vẻ ổn về đầu vào và đầu ra, kiểm tra:

  str2Hex←{∊{'0123456789ABCDEF'[1+{(2⍴16)⊤⍵}⍵]}¨{¯1+⎕AV⍳⍵}⍵}
  str2Hex ⎕AV[2,1,1,1,1,1,1]
01000000000000
  str2Hex C ⎕AV[2,1,1,1,1,1,1]
0100DE188941A3
  str2Hex C C ⎕AV[2,1,1,1,1,1,1]
01000000000000
  str2Hex C ⎕AV[14],'this is a keythis is some data to encrypt'
0D746869732069732061206B6579B5DB3F691F9296966521F3AE2821F3EA43D49F53BD3F6482847BCD4E
  C C ⎕AV[14],'this is a keythis is some data to encrypt'

this is a keythis is some data to encrypt

  str2Hex C 'Sthis is a rather long key because the value of S is 83 so the key length must matchand this is the data to be encrypted'
5374686973206973206120726174686572206C6F6E67206B65792062656361757365207468652076616C7565206F662053
  20697320383320736F20746865206B6579206C656E677468206D757374206D61746368961F2C8FA3259BA3665B6D
  6BDFBCAC8B8EFAFE96423D21FC3B13606316710411D886EE07

  C C 'Sthis is a rather long key because the value of S is 83 so the key length must matchand this is the data to be encrypted'
Sthis is a rather long key because the value of S is 83 so the key length must matchand this is th
  e data to be encrypted

Có tất cả có thể được giảm ... nhưng ví dụ, làm cho ít hơn hàm xor có thể có nghĩa là làm cho nó ít chung hơn ...


0

Rỉ sét 349

fn rc4(n:Vec<u8>)->Vec<u8>{let(mut s,mut j,mut t,l)=((0..256).collect::<Vec<usize>>(),0,0,n[0] as usize);let(key,msg)=n[1..].split_at(l);(0..256).fold(0,|a,i|{j=(a+s[i]+key[i%l] as usize)%256;t=s[i];s[i]=s[j];s[j]=t;j});j=0;(1..).zip(msg.iter()).map(|(i,b)|{j=(j+s[i])%256;t=s[i];s[i]=s[j];s[j]=t;s[(s[i]+s[j])%256]as u8^b}).collect::<Vec<u8>>()}

Cái này khá lớn, tôi hy vọng có thể ai đó có thể cung cấp một số gợi ý.

vô dụng: trên sân chơi play.rust-lang.org


Đề xuất kthay vì keymthay vì msgfoo&255thay vì(foo)%256
trần
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.