Shifty XORyption

15

Schreiben Sie ein Programm oder eine Funktion (oder eine Reihe von Programmen / Funktionen) zum Ver- und Entschlüsseln von Daten gemäß der folgenden Spezifikation:

Verschlüsselung

  1. Berechnen Sie einen XOR-Hash der Eingabe, indem Sie jedes Byte miteinander XOR-verknüpfen.

  2. XOR jedes Byte der Eingabe von diesem Hash.

  3. Verschieben Sie das Ergebnis um vier Bits nach links.

  4. Füllen Sie die linke Seite mit den ersten vier Bits des XOR-Hashs auf.

  5. Füllen Sie die rechte Seite mit den letzten vier Bits des XOR-Hashs auf.

Beispiel

  • Eingegebene Eingabe: "G0lf"( 0x47306C66)

  • Berechnen Sie den XOR-Hash: 0x47 ^ 0x30 ^ 0x6C ^ 0x66 = 0x7D

  • XOR jedes Byte von Hash: 0x3A4D111B

  • Erwartetes Ergebnis (nach Shift und Pad): "s¤Ñ\x11½"( 0x73A4D111BD)

Regeln

  • Ihr Programm / Ihre Funktion kann Eingaben / Ausgaben jeglicher Art in der von Ihnen gewählten Golfsprache (String, Byte Array usw.) vornehmen, solange die Eingaben / Ausgaben die tatsächlichen Bytes sind. Beispielsweise können Sie eine hexadezimale Zeichenfolge nicht ausgeben.

  • Verschlüsselung und Entschlüsselung können in getrennte Programme (Punktzahl entspricht der kombinierten Größe) oder in ein einzelnes Programm unterteilt werden. Einzelne Methoden können ein Argument annehmen, ob sie verschlüsseln oder entschlüsseln sollen.

  • Die Eingabe für die Verschlüsselung muss mindestens 1 Byte groß sein.

  • Die Eingabe für die Entschlüsselung muss mindestens 2 Byte betragen.

  • Nicht druckbare Bytes müssen in der Ausgabe nicht maskiert werden.

nderscore
quelle
1
Könnte ein Dezimalarray als Ausgabeform verwendet werden?
ɐɔıɐɔuʇǝɥʇs
@ ɐɔıɐɔuʇɥʇs Es ist akzeptabel, Eingaben und Ausgaben als Array von Ganzzahlen zur Darstellung von Bytes zu verwenden.
Nderscore
Gibt es eine maximale Eingabelänge (z. B. 14 Byte (56 Bit), damit das Endergebnis in eine 64-Bit-Ganzzahl passt)?
Türklinke
1
Nur eine Anmerkung: Aus kryptografischer Sicht ist dies keine Verschlüsselung, da es keinen Schlüssel (oder einen 0-Bit-Schlüssel) gibt.
Paŭlo Ebermann
1
Ich warte nur darauf, dass jemand etwas über das Niemals-Rolling Ihrer eigenen Verschlüsselung
schreibt

Antworten:

9

CJam, 28 + 27 = 55 Bytes

Für jeden Teil stelle ich ein Programm vor, das erwartet, dass die Eingabe / Ausgabe in Form eines Integer-Arrays erfolgt, und eines, das eine Zeichenfolge verwendet. Die obige Byteanzahl gilt für die Integer-Array-Version, das verknüpfte Skript und die Erläuterung gelten jedoch für die auf Zeichenfolgen basierende Version (die zum Testen des in der Frage angegebenen Beispiels verwendet werden kann).

Verschlüsselung

q~_:^_GbYUe[\@f^Gfbe_*2/Gfbp
q:i_:^_GbYUe[\@f^Gfbe_*2/Gfb:c

Entschlüsselung

q~{_G/\G%}%)\(G*@+\2/Gfbf^p
q:i{_G/\G%}%)\(G*@+\2/Gfbf^:c

Hier ist ein Testskript, das einen vollständigen Roundtrip durchführt und den verschlüsselten Code druckt, bevor die Entschlüsselung erneut durchgeführt wird.

Erläuterung

q:i_:^_GbYUe[\@f^Gfbe_*2/Gfb:c
q:i                            e# Read the input and convert characters to byte values.
   _:^                         e# Duplicate and fold XOR onto the characters to get 
                               e# the hash.
      _Gb                      e# Duplicate and convert to base 16 to get nibbles.
         YUe[                  e# Pad to width 2 with zeroes.
             \@                e# Pull up other copy and integer array.
               f^              e# XOR each integer with the hash.
                 Gfbe_         e# Convert each result to base 16 and flatten that.
                      *        e# Join the hash nibbles with this array.
                       2/      e# Split into pairs.
                         Gfb   e# Interpret each pair as base 16.
                            :c e# Convert each integer to a character.

q:i{_G/\G%}%)\(G*@+\2/Gfbf^:c
q:i                            e# Read the input and convert characters to byte values.
   {      }%                   e# Map this block onto each byte.
    _G/\G%                     e# Get the two base 16 digits individually.
            )\(                e# Slice off the last and first nibble.
               G*@+\           e# Combine into byte (the hash) and swap with array.
                    2/Gfb      e# Split array into pairs and interpret each as base 16.
                         f^    e# XOR each with the hash.
                           :c  e# Convert each integer to a character.
Martin Ender
quelle
6

CJam, 36 + 34 = 70 Bytes

Ein etwas anderer Ansatz unter Verwendung von Binärformen

Verschlüsseln :

q_:^:Hf^H+{i2b8Ue[}%)4/~@\]e_8/2fb:c

Wie es funktioniert:

q_:^                                  e# Read input as string, copy and XOR all the chars
    :Hf^                              e# Store the XOR in H and XOR each char with H
        H+                            e# Append H to the char array
          {       }%                  e# On each of the elements in the array
           i2b                        e# Convert the ASCII value to binary
              8Ue[                    e# Pad with 0 so that the length is 8
                    )                 e# Pop out the last array element, which is H
                     4/~@\            e# Put first 4 bits of H before the input array
                                      e# And rest 4 after it
                          ]e_8/       e# Flatten everything into a single array and group
                                      e# into pieces of 8 bits
                               2fb:c  e# Convert each 8 bit part to integer and then to
                                      e# its character form

Entschlüsseler :

q{i2b8Ue[4/~}%)\(@+2b\:+8/2fb\f^:c

Wie es funktioniert:

q{          }%                      e# For each character of the input string
  i2b                               e# Convert to ASCII code and then to its binary form
     8Ue[                           e# Pad with enough 0 so that length is 8 bit
         4/~                        e# Split into parts of 4 and unwrap
              )\(@+                 e# Take out the first and last 4 bit group and join
                                    e# them together to get the XOR Hash H
                   2b\              e# Convert H to decimal form and swap to put the
                                    e# remaining converted input array on top
                      :+8/          e# Join all bits together and split into groups of 8
                          2fb       e# Convert each 8 but group to decimal form
                             \f^    e# Swap to put H on top and XOR each number with H
                                :c  e# Get character from each of the ASCII value

Probieren Sie den Ver- und Entschlüsseler online aus

Optimierer
quelle
6

Pyth, 69 Bytes

Ksm>+0jCd16_2zJ?,hKeKQmxFdCcK2=KsmmxFkC,dJc?tPKQK2smCid16c?KQ++hJKeJ2

Dies kombiniert Verschlüsselung und Entschlüsselung. Fügen Sie einfach ein 0Argument für die Verschlüsselung oder 1Entschlüsselung hinzu. Der Grund dafür ist einfach. Das Konvertieren von Strings in Bits (oder 4-Bit-Integer) oder umgekehrt ist in Pyth wirklich sehr lang. Durch die Kombination der beiden Funktionen in einem Programm kann ich eine Menge Bytes sparen.

Online-Demonstrationen: Ver- und Entschlüsselung .

Erläuterung:

Der erste Teil konvertiert die Eingabe in eine Liste mit 4-Bit-Ganzzahlen (jedes Zeichen wird in 2 4-Bit-Ganzzahlen konvertiert) und speichert sie in K.

  m          z   map each character d of input (=z) to:
       Cd            the ascii-value of d
      j  16          convert the result into base 16
   >+0     _2        insert a zero to the front and take the last 2 values
                     (so that each char gets mapped to exactly 2 numbers)
Ks               chain all these tuples and assign them to K

Der zweite Teil bestimmt die Hash-Werte und speichert sie in J. Wenn Q==0es sie mit xor berechnet, nimmt es andernfalls den ersten und letzten Wert von an K.

 ?     Q           ... if Q (=second input) else ...
  ,hKeK            [K[0], K[-1]]
        m   CcK2   map each d of zipped(K chopped into pairs) to:
                   [zipped(...) gives me 2 lists, one with the values of the even indices, and one with the odd indices]
         xFd           fold the list d by xor
J                  store the result in J (this is the hash value)

Der nächste Teil erledigt das xor unter Verwendung der Hash-Werte. Wenn Q == 0es auf der vollständigen Liste ausgeführt wird K, sonst nur auf der Liste Kohne den ersten und letzten Wert.

=KsmmxFkC,dJc?tPKQK2
             ?tPKQK    K[1:-1] if Q else K 
   m        c      2   map each d of [... chopped into pairs] to:
    m   C,dJ              map each pair k of zip(d,J) to:
     xFk                     apply xor to the 2 values in k
=Ks                    chain all these tuples and assign them to K

Und der letzte Teil konvertiert Kzurück in Zeichen:

smCid16c?KQ++hJKeJ2
        ?KQ++hJKeJ    K if Q else J[0] + K + J[1]
 m     c          2   map each pair of [... chopped into pairs] to:
   id16                  convert d into a single integer
  C                      convert to char
s                     join all chars and print
Jakube
quelle
0

Javascript ( ES6 ) 83 + 73 = 156

Beide Funktionen nehmen Eingaben als und geben ein Array von Zahlen zur Darstellung von Bytes aus.

Verschlüsseln Sie 85 84 83

E=s=>s.concat((h=s.reduce((x,y)=>x^y))<<4&240^h).map(x=>a<<4&240|(a=x^h)>>4,a=h>>4)

75 entschlüsseln 73

D=s=>s.map(x=>(a<<4&240|(a=x)>>4)^h,h=(a=s.shift())&240|s[~-s.length]&15)

Demonstration (nur Firefox)

E=s=>s.concat((h=s.reduce((x,y)=>x^y))<<4&240^h).map(x=>a<<4&240|(a=x^h)>>4,a=h>>4)
D=s=>s.map(x=>(a<<4&240|(a=x)>>4)^h,h=(a=s.shift())&240|s[~-s.length]&15)

toHexString = x=>'0x'+x.map(y=>y.toString(16)).join('')

input = [...'G0lf'].map(x=>x.charCodeAt());
document.write('Input: ' + toHexString(input) + '<br />');

encrypted = E(input);
document.write('Encrypted: ' + toHexString(encrypted) + '<br />');

decrypted = D(encrypted);
document.write('Decrypted: ' + toHexString(decrypted) + '<br />');


Verwenden der Zeichenfolgen 131 + 129 = 260

Und nur zum Spaß ... hier sind einige Versionen, die stattdessen Zeichenfolgen für die Eingabe / Ausgabe verwenden.

E=(s,h=0)=>[for(x of s)(h^=y=x.charCodeAt(),y)].concat(h<<4&240^h).map(x=>String.fromCharCode(a<<4&240|(a=x^h)>>4),a=h>>4).join('')

D=s=>(s=[s.charCodeAt(j=i)for(i in s)]).map(x=>String.fromCharCode((a<<4&240|(a=x)>>4)^h),h=(a=s.shift())&240|s[~-j]&15).join('')

E('G0lf') // 's¤Ñ\x11½'
D('s¤Ñ\x11½') // 'G0lf'
nderscore
quelle