Mã hóa CryptSaber


11

Thực hiện một chương trình mã hóa CodesSaber , như được mô tả dưới đây. Hướng dẫn:

  • Mục nhỏ nhất, tính bằng byte, thắng.
    • Tuy nhiên, trong một lần khởi hành từ tiêu chuẩn , bạn có thể đăng các mục thú vị, ngay cả khi chúng không phải là mục golf nghiêm túc.
  • Một mục thường sẽ là một chương trình lấy bản rõ từ đầu vào tiêu chuẩn và ghi bản mã vào đầu ra tiêu chuẩn, với khóa được chỉ định (bởi người dùng) theo cách bạn muốn.
    • Tuy nhiên, nếu bạn muốn thực hiện điều này như một thủ tục, điều đó cũng tốt.
  • IV phải đến từ một trình tạo số giả ngẫu nhiên an toàn bằng mật mã. Nếu ngôn ngữ của bạn không hỗ trợ điều đó, hãy chọn một ngôn ngữ khác. ;-)
  • Vui lòng không sử dụng bất kỳ thư viện, cuộc gọi hệ thống hoặc hướng dẫn cụ thể nào về tiền điện tử (trừ PRNG, như quy định ở trên). Tất nhiên, các hoạt động bitwise cấp thấp chung là ổn.

CodesSaber là một biến thể của RC4 / Arcfour, vì vậy tôi sẽ bắt đầu bằng cách mô tả cái sau, sau đó những thay đổi mà CodesSaber thực hiện.

0. RC4 / Arcfour

Arcfour được chỉ định đầy đủ ở nơi khác , nhưng để hoàn thiện, tôi sẽ mô tả nó ở đây. (Trong trường hợp có bất kỳ sự khác biệt nào giữa dự thảo Internet và mô tả này, thì trước đây là quy định.)

Thiết lập khóa

Thiết lập hai mảng SS2cả hai chiều dài 256, k_1là byte đầu tiên của khóa và k_nlà byte cuối cùng.

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

( S2được lấp đầy với các byte của khóa, lặp đi lặp lại, cho đến khi tất cả 256 byte được lấp đầy.)

Sau đó, khởi tạo jthành 0 và xáo trộn 256 lần:

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

Điều này hoàn thành thiết lập chính. Các S2mảng không còn được sử dụng ở đây, và có thể được chà.

Tạo dòng mật mã

Khởi tạo ijvề 0, sau đó tạo luồng khóa như sau:

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

Mã hóa / giải mã dữ liệu

  • Để mã hóa, XOR đầu ra dòng chính với bản rõ
  • Để giải mã, XOR đầu ra dòng chính với bản mã

1. Mật mã

CodesSaber (đó là những gì chúng tôi đang thực hiện trong câu hỏi này) là một biến thể của RC4 / Arcfour theo hai cách:

IV 10 byte / nonce

Khi mã hóa tin nhắn, cần lấy 10 byte ngẫu nhiên, chẳng hạn như thông qua /dev/urandomvà được ghi vào 10 byte đầu tiên của đầu ra được mã hóa. Khi giải mã một tin nhắn, 10 byte đầu tiên của đầu vào là IV được sử dụng để mã hóa nó.

Giai đoạn thiết lập khóa RC4 / Arcfour được chạy với passphrase || IVtư cách là khóa, trong đó passphrasecụm mật khẩu do người dùng chỉ định, IVnhư được mô tả ở trên và ||được ghép nối. Vì vậy, một cụm mật khẩu của "Xin chào, thế giới!" và IV của "supercalif" (tuy nhiên không chắc là :-P) sẽ dẫn đến một khóa "Xin chào, thế giới! supercalif".

Nhiều lần lặp lại thiết lập khóa

Để giúp ngăn ngừa lỗ hổng khiến mã hóa WEP bị hỏng hoàn toàn, vòng lặp xáo trộn của giai đoạn thiết lập khóa của RC4 được chạy với số lần người dùng chỉ định. Giá trị của jnên được giữ lại giữa các lần lặp.

2. Vectơ kiểm tra

Dưới đây là một số vectơ kiểm tra bạn có thể sử dụng để kiểm tra các chương trình của mình. Hơn nữa, ossifrage squeamish đã tạo ra một công cụ mã hóa & giải mã CodesSaber mà bạn có thể sử dụng để xác nhận kết quả của mình.

Bạn chỉ cần thực hiện chương trình mã hóa. Bạn không cần cung cấp chương trình giải mã, nhưng đầu ra của chương trình mã hóa của bạn phải làm tròn chính xác với đầu vào ban đầu khi được xử lý với chương trình giải mã được triển khai chính xác bằng khóa chính xác.

Câu trả lời:


7

Bình thường, 100 byte

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

Kịch bản này sử dụng các $lệnh, cho phép thực thi mã Python. Để ngăn chặn việc thực thi mã độc trên máy chủ, lệnh này bị vô hiệu hóa trong trình biên dịch trực tuyến. Bạn phải chạy nó với trình biên dịch ngoại tuyến mà bạn có thể tìm thấy ở đây .

Đầu vào có định dạng:

secret key
5 (number of repeats)
secret message

Chương trình xuất ra chuỗi được mã hóa, có thể chứa các ký tự không thể in được. Nếu bạn muốn xác minh nó bằng Công cụ mã hóa và giải mã CryptSaber , bạn có thể sử dụng đoạn mã sau để chuyển chuỗi thành một chuỗi các chữ số thập lục phân.

$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 không hỗ trợ số giả ngẫu nhiên bảo mật bằng mật mã và nhập chúng từ Python tốn 25 byte. Một mã ngắn hơn, sử dụng trình tạo số giả ngẫu nhiên của Pyth's / Python và cũng hoạt động trong trình biên dịch trực tuyến là:

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

Dùng thử trực tuyến: trả về một chuỗi hoặc một chuỗi các chữ số thập lục phân

Mã này không có gì đặc biệt. Chỉ cần rất nhiều bài tập bẩn và sử dụng lại ngay lập tức các kết quả được tính toán và áp dụng hai lần thủ thuật hoán đổi danh sách .

Giải trình:

                                  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

Rõ ràng, các hàm Pyth tích hợp không có số giả ngẫu nhiên được bảo mật bằng mật mã . Bạn có thể giữ nguyên mục nhập của mình và nó sẽ không đủ điều kiện để đánh dấu màu xanh lục hoặc bạn có thể tạo một phiên bản sử dụng urandom(có thể là một mục riêng nếu bạn muốn) nếu bạn quan tâm đến việc "chiến thắng". :-)
Chris Jester-Young

@ ChrisJester-Young Xin lỗi về điều đó. Tôi đã không nghĩ rằng trình tạo số ngẫu nhiên của Python là không an toàn. Sửa nó với chi phí 25 byte.
Jakube

4

Python 2 - 373 350 326 317 byte

Pyth có thể đến sau. Xác định một hàm, c(p,d,r,m)trong đó lấy danh sách byte cho cụm mật khẩu và dữ liệu, và int cho các lần lặp lại và chế độ mã hóa khi 1 và giải mã khi 0. Điều này là do sự khác biệt duy nhất trong chúng là xử lý IV. Trả về danh sách byte.

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

Dưới đây là một số mã kiểm tra / Hàm trợ giúp:

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)

Bạn chỉ cần viết một chương trình mã hóa. Vì vậy, bạn có thể loại bỏ else:v,d=d[:10],d[10:]một phần.
Jakube

3

Ruby - 263 ký tự

Đây là câu trả lời Ruby của tôi cho câu hỏi ban đầu về stackoverflow vào năm 2010! Nó là một bộ mã hóa và giải mã tất cả trong một chương trình

Thông số là:
e hoặc d (đối với mã hóa hoặc giải mã)
chìa khóa
số lần

$ 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 byte

Chấp nhận một số lần lặp và khóa trộn số đếm trên dòng lệnh, sau đó mã hóa mọi thứ trên stdin thành stdout. Cái này sử dụng chức năng thư viện BSD / Darwin arc4random(), là PRNG dựa trên RC4. Nó tự động gieo hạt giống, vì vậy kết quả sẽ khác nhau mỗi lần.

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]);}}

Phiên bản gọn gàng hơn:

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]);
  }
}

Thí dụ:

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

1

Python - 266 ký tự

Đây là câu trả lời Python của tôi cho câu hỏi ban đầu về stackoverflow vào năm 2010! Nó là một bộ mã hóa và giải mã tất cả trong một chương trình

Thông số là:
e hoặc d (đối với mã hóa hoặc giải mã)
chìa khóa
số lần

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

Phiên bản này cố gắng hợp nhất 2 vòng lặp của RC4 thành một (tiết kiệm 11 byte cho đến nay ...)

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