Shifty XORyption

15

Écrivez un programme ou une fonction (ou un ensemble de programmes / fonctions) pour crypter et décrypter les données en fonction des spécifications suivantes:

Chiffrement

  1. Calculez un hachage XOR de l'entrée en XOR-ing chaque octet avec l'autre.

  2. XOR chaque octet de l'entrée par ce hachage.

  3. Décale le résultat de quatre bits vers la gauche.

  4. Remplissez le côté gauche avec les quatre premiers bits du hachage XOR.

  5. Remplissez le côté droit avec les quatre derniers bits du hachage XOR.

Exemple

  • Entrée donnée: "G0lf"( 0x47306C66)

  • Calculer le hachage XOR: 0x47 ^ 0x30 ^ 0x6C ^ 0x66 = 0x7D

  • XOR chaque octet par hachage: 0x3A4D111B

  • Résultat attendu (après shift et pad): "s¤Ñ\x11½"( 0x73A4D111BD)

Règles

  • Votre programme / fonction peut entrer / sortir de n'importe quel type qui a du sens dans la langue de golf de votre choix (chaîne, tableau d'octets, etc.) tant que l'entrée / sortie sont les octets réels. Par exemple, vous ne pouvez pas générer de chaîne hexadécimale.

  • Le chiffrement et le déchiffrement peuvent être séparés dans des programmes séparés (le score sera leur taille combinée) ou un seul. Les méthodes uniques peuvent prendre un argument pour savoir si elles doivent chiffrer ou déchiffrer.

  • L'entrée pour le chiffrement peut avoir une taille d'au moins 1 octet.

  • L'entrée pour le déchiffrement peut être d'au moins 2 octets.

  • Les octets non imprimables n'ont pas besoin d'être échappés dans la sortie.

nderscore
la source
1
Un tableau décimal pourrait-il être utilisé comme formulaire de sortie?
ɐɔıʇǝɥʇuʎs
@ ɐɔıʇɥʇuʎs Il serait acceptable de prendre en entrée et en sortie un tableau d'entiers pour représenter des octets.
nderscore
Existe-t-il une longueur d'entrée maximale (par exemple, 14 octets (56 bits), de sorte que le résultat final rentre dans un entier 64 bits)?
Poignée de porte
1
Juste une note: d'un point de vue cryptographique, ce n'est pas un cryptage, car il n'a pas de clé (ou une clé 0 bit).
Paŭlo Ebermann
1
J'attends juste que quelqu'un poste quelque chose sur le fait de ne jamais rouler votre propre cryptage, en ignorant le site sur
lequel

Réponses:

9

CJam, 28 + 27 = 55 octets

Pour chaque partie, je présente un programme qui s'attend à ce que l'entrée / sortie soit sous la forme d'un tableau d'entiers et un autre qui utilise une chaîne. Le nombre d'octets ci-dessus concerne la version du tableau d'entiers, mais le script lié et l'explication concernent la version basée sur des chaînes (qui peut être utilisée pour tester l'exemple donné dans la question).

Chiffrement

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

Décryptage

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

Voici un script de test qui fait un aller-retour complet et imprime le code crypté avant de refaire le décryptage.

Explication

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
la source
6

CJam, 36 + 34 = 70 octets

Une approche un peu différente en utilisant des formes binaires

Encrypter :

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

Comment ça fonctionne:

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

Decrypter :

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

Comment ça fonctionne:

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

Essayez le chiffreur et le déchiffreur en ligne

Optimiseur
la source
6

Pyth, 69 octets

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

Cela combine le cryptage et le décryptage, ajoutez simplement un 0argument as pour le cryptage ou un 1pour le décryptage. La raison en est simple. La conversion de chaînes en bits (ou entier 4 bits) ou l'inverse est vraiment très longue en Pyth. En combinant les deux fonctions en un seul programme, je peux économiser beaucoup d'octets.

Démonstrations en ligne: chiffrement et déchiffrement .

Explication:

La première partie convertit l'entrée en une liste d'entiers 4 bits (chaque caractère est converti en 2 entiers 4 bits) et la stocke 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

La deuxième partie détermine les valeurs de hachage et les stocke J. S'il les Q==0calcule par xor, sinon il prend la première et la dernière valeur de 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)

La partie suivante fait le xor en utilisant les valeurs de hachage. Lorsqu'il Q == 0est effectué sur la liste complète K, sinon uniquement sur la liste Ksans la première et la dernière valeur.

=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

Et la dernière partie se reconvertit Ken caractères:

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
la source
0

Javascript ( ES6 ) 83 + 73 = 156

Les deux fonctions prennent en entrée et sortent un tableau de nombres pour représenter les octets.

Crypter 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)

Déchiffrer 75 73

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

Démonstration (Firefox uniquement)

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 />');


Utilisation des chaînes 131 + 129 = 260

Et juste pour le plaisir ... voici quelques versions qui utilisent des chaînes d'entrée / sortie à la place.

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
la source