Широкий XORyption


15

Напишіть програму або функцію (або набір програм / функцій) для шифрування та дешифрування даних з урахуванням наступних специфікацій:

Шифрування

  1. Обчисліть ХОР хеш вхідних даних, по XOR-кожний байт один з одним.

  2. XOR кожен байт вводу цього хеша.

  3. Зсуньте результат на чотири біти вліво.

  4. Прокладіть ліву сторону першими чотирма бітами хеша XOR.

  5. Прокладіть праву сторону останніми чотирма бітами хешу XOR.

Приклад

  • Даний вхід: "G0lf"( 0x47306C66)

  • Обчисліть хеш XOR: 0x47 ^ 0x30 ^ 0x6C ^ 0x66 = 0x7D

  • XOR кожен байт по хешу: 0x3A4D111B

  • Очікуваний результат (після зміни та майданчика): "s¤Ñ\x11½"( 0x73A4D111BD)

Правила

  • Ваша програма / функція може вводити / виводити будь-який тип, який має сенс у вашій мові для гольфу (String, Byte Array тощо) , якщо введення / вихід є фактичними байтами. Наприклад, ви не можете виводити шістнадцятковий рядок.

  • Шифрування та дешифрування можна розділити на окремі програми (оцінка буде їх комбінованим розміром) або на одну. Одиничні методи можуть взяти аргумент щодо того, чи слід шифрувати чи розшифровувати.

  • Вхід для шифрування можна очікувати розміром щонайменше 1 байт.

  • Вхідні дані для дешифрування можуть бути принаймні 2 байтами.

  • Невидані байти не потрібно уникати у висновку.


1
Чи можна використовувати десятковий масив як форму виводу?
ɐɔıʇǝɥʇuʎs

@ ɐɔıʇɥʇuʎs Було б прийнятно приймати вхід і вихід як масив цілих чисел для представлення байтів.
nderscore

Чи є максимальна довжина вводу (наприклад, 14 байт (56 біт), щоб кінцевий результат вписався в 64-бітове ціле число)?
Дверна ручка

1
Лише зауваження: з точки зору криптографії це не шифрування, оскільки в ньому немає ключа (або 0-бітного ключа).
Paŭlo Ebermann

1
Я просто чекаю, коли хтось опублікує щось про те, щоб ніколи не прокручувати власне шифрування, ігноруючи сайт, на якому він знаходиться ...
user253751

Відповіді:


9

CJam, 28 + 27 = 55 байт

Для кожної частини я представляю одну програму, яка очікує, що введення / вихід має форму цілого масиву, і та, яка використовує рядок. Наведений вище кількість байтів призначений для цілої версії масиву, але пов'язаний скрипт та пояснення призначені для рядкової версії (яка може бути використана для перевірки прикладу, наведеного у питанні).

Шифрування

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

Розшифрування

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

Ось тестовий скрипт, який здійснює повну подорож і друкує зашифрований код, перш ніж повторити розшифровку.

Пояснення

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.

6

CJam, 36 + 34 = 70 байт

Трохи інший підхід із використанням бінарних форм

Шифрувач :

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

Як це працює:

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

Розшифрувач :

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

Як це працює:

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

Спробуйте шифрувати та дешифрувати в Інтернеті


6

Pyth, 69 байт

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

Це поєднує в собі шифрування та дешифрування, просто додайте 0як аргумент для шифрування або як 1для дешифрування. Причина цього проста. Перетворення рядків у біти (або 4-бітове ціле число) або зворотне дійсно дійсно довге в Pyth. Поєднуючи обидві функції в одну програму, я можу зберегти багато байтів.

Онлайн-демонстрації: шифрування та дешифрування .

Пояснення:

Перша частина перетворює вхід у список 4-бітових цілих чисел (кожне знаряддя перетворюється на 2 4-розрядне ціле число) і зберігає його 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

Друга частина визначає хеш-значення та зберігає їх у J. Якщо Q==0він обчислює їх за допомогою xor, в іншому випадку він приймає перше і останнє значення 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)

У наступній частині виконується xor з використанням хеш-значень. Коли Q == 0він виконується у повному списку K, інакше лише у списку Kбез першого та останнього значення.

=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

І остання частина перетворюється Kназад на символи:

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

0

Javascript ( ES6 ) 83 + 73 = 156

Обидві функції приймають введення як і виводять масив чисел для представлення байтів.

Шифруйте 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 73

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

Демонстрація (лише для 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 />');


Використання рядків 131 + 129 = 260

І просто для розваги ... ось кілька версій, які використовують рядки для введення / виводу замість цього.

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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.