CipherSaber加密


11

实施一个CipherSaber加密程序,如下所述。指导原则:

  • 以字节为单位的最小条目获胜。
    • 但是,与规范规范不同的是,欢迎您发布有趣的条目,即使它们不是认真的高尔夫条目。
  • 条目通常是一个程序,该程序从标准输入中获取纯文本,并将密文写入到标准输出中,并使用您喜欢的某种方式(由用户指定)来指定密钥。
    • 但是,如果您希望将此作为一个过程来实现,那也很好。
  • IV必须来自加密安全的伪随机数生成器。如果您的语言不支持,请选择其他语言。;-)
  • 请不要使用任何特定于加密货币的库,系统调用或指令(上述PRNG除外)。当然,通用的低级按位运算也可以。

CipherSaber是RC4 / Arcfour的变体,因此我将先描述后者,然后再对CipherSaber进行更改。

0. RC4 / Arcfour

Arcfour在其他地方已完全指定,但出于完整性考虑,我将在此处进行描述。(如果互联网草稿与本说明存在任何差异,则前者为规范性。)

按键设定

设置两个数组SS2,两个数组的长度均为256,其中k_1是密钥的第一个字节,k_n也是最后一个。

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

S2一次又一次地填充密钥的字节,直到所有256个字节都被填充。)

然后,初始化j为0,并随机播放256次:

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

这样就完成了密钥设置。该S2阵列在这里不再使用,可以清理。

密码流生成

初始化ij为0,则生成密钥流,如下所示:

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

加密/解密数据

  • 要进行加密,请将密钥流输出与明文进行异或
  • 要解密,请将密钥流输出与密文异或

1. CipherSaber

CipherSaber(这是我们在此问题中实现的)是RC4 / Arcfour的两种变体:

10字节IV /一次

加密消息时,应获得10个随机字节,例如via /dev/urandom,并将其写入加密输出的前10个字节中。解密消息时,输入的前10个字节是用于加密消息的IV。

RC4 / Arcfour密钥设置阶段passphrase || IV以密钥运行,其中passphrase用户指定的密码短语IV如上所述,||是串联的。因此,使用“你好,世界!”的密码短语。IV的“ supercalif”(但是不太可能是:-P)将导致出现“ Hello,world!supercalif”键。

按键设置的多次迭代

为了帮助防止使WEP加密完全失效的漏洞,RC4密钥设置阶段的改组循环运行了用户指定的次数。的值j应在两次迭代之间保留。

2.测试向量

这是一些您可以用来测试程序的测试向量。此外,吱吱作响的ossifrage还创建了一个CipherSaber加密和解密工具,可用于验证结果。

您只需要实现加密程序。您不需要提供解密程序,但是在使用正确的密钥通过正确实施的解密程序进行处理时,加密程序的输出必须正确地往返于原始输入。

Answers:


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加密和解密工具进行验证,则可以使用以下代码,该代码将字符串转换为一系列十六进制数字。

$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伪随机数生成器,并且还可以在在线编译器中使用:

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

在线尝试:返回字符串一系列十六进制数字

该代码没什么特别的。只是很多肮脏的分配和计算结果的立即重用,并应用了两次列表交换技巧。

说明:

                                  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如果您关心“获胜”,则可以制作一个使用的版本(如果愿意,可以使用单独的条目)。:-)
克里斯·杰斯特·杨

@ ChrisJester-Young抱歉。我没想到Python的随机数生成器是如此不安全。已将其更正为25个字节。
雅库布

4

蟒2 - 373个 350 326 317字节

Pyth可能稍后再来。定义一个函数,c(p,d,r,m)该函数将字节列表用于密码短语和数据,将int用于重复,并且模式将在1时加密并在0时解密。这是因为它们之间的唯一区别在于处理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

这是一些测试代码/ Helper函数:

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:]零件。
2015年

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。这使用了BSD / Darwin库函数arc4random(),它是基于RC4的PRNG。它会自动进行播种,因此每次的结果都会有所不同。

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

整理版本:

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

Python-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]))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.