Advertisement
Guest User

Untitled

a guest
Apr 24th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.93 KB | None | 0 0
  1. #include <iostream>
  2. #include <array>
  3. #include <cstdio>
  4. #include <tuple>
  5. #include <vector>
  6. #include <string>
  7.  
  8. using namespace std;
  9.  
  10. typedef unsigned int word;
  11. typedef unsigned char byte;
  12.  
  13. const word ONE = 1;
  14. const word BYTE_MASK = 0xff;
  15.  
  16. word rotate(word num, int count) {
  17.     return (num << count) | (num >> (32 - count));
  18. }
  19.  
  20. void quarterround(word& y0, word& y1, word& y2, word& y3) {
  21.     word z1 = y1 ^ rotate(y0 + y3, 7);
  22.     word z2 = y2 ^ rotate(z1 + y0, 9);
  23.     word z3 = y3 ^ rotate(z2 + z1, 13);
  24.     word z0 = y0 ^ rotate(z3 + z2, 18);
  25.  
  26.     y0 = z0, y1 = z1, y2 = z2, y3 = z3;
  27. }
  28.  
  29. void rowround(array <word, 16>& m) {
  30.     quarterround(m[0], m[1], m[2], m[3]);
  31.     quarterround(m[5], m[6], m[7], m[4]);
  32.     quarterround(m[10], m[11], m[8], m[9]);
  33.     quarterround(m[15], m[12], m[13], m[14]);
  34. }
  35.  
  36. void columnround(array <word, 16>& m) {
  37.     quarterround(m[0], m[4], m[8], m[12]);
  38.     quarterround(m[5], m[9], m[13], m[1]);
  39.     quarterround(m[10], m[14], m[2], m[6]);
  40.     quarterround(m[15], m[3], m[7], m[11]);
  41. }
  42.  
  43. void doubleround(array <word, 16>& m) {
  44.     columnround(m);
  45.     rowround(m);
  46. }
  47.  
  48. word littleendian(byte b0, byte b1, byte b2, byte b3) {
  49.     return b0 + (ONE << 8) * b1 + (ONE << 16) * b2 + (ONE << 24) * b3;
  50. }
  51.  
  52. // 0 & 0 == 0
  53. // 0 & 1 == 0
  54. // 1 & 0 == 0
  55. // 1 & 1 == 1
  56. tuple <byte, byte, byte, byte> littleendian_inv(word n) {
  57.     byte b0 = (n >> 0)  & BYTE_MASK;
  58.     byte b1 = (n >> 8)  & BYTE_MASK;
  59.     byte b2 = (n >> 16) & BYTE_MASK;
  60.     byte b3 = (n >> 24) & BYTE_MASK;
  61.  
  62.     return make_tuple(b0, b1, b2, b3);
  63. }
  64.  
  65. // The Salsa20 hash function
  66. void hash_func(array <byte, 64>& input) {
  67.     array <word, 16> seq;
  68.     for (int i = 0; i < 16; i++) {
  69.         int idx = i * 4;
  70.         seq[i] = littleendian(input[idx], input[idx + 1], input[idx + 2], input[idx + 3]);
  71.     }
  72.  
  73.     auto backup{seq};
  74.  
  75.     for (int i = 0; i < 10; i++) {
  76.         doubleround(seq);
  77.     }
  78.  
  79.     for (int i = 0; i < 16; i++) {
  80.         // Overflow == mod 2^32, no UB
  81.         seq[i] += backup[i];
  82.     }
  83.  
  84.     for (int i = 0; i < 16; i++) {
  85.         int idx = i * 4;
  86.         tie(input[idx], input[idx + 1], input[idx + 2], input[idx + 3]) = littleendian_inv(seq[i]);
  87.     }
  88. }
  89.  
  90. // The Salsa20 expansion function for 32 byte key
  91. array <byte, 64> expansion_32(const array <byte, 32>& key, const array <byte, 16>& n) {
  92.     const static array <byte, 4> sigma0{101, 120, 112,  97};
  93.     const static array <byte, 4> sigma1{110, 100,  32,  51};
  94.     const static array <byte, 4> sigma2{ 50,  45,  98, 121};
  95.     const static array <byte, 4> sigma3{116, 101,  32, 107};
  96.  
  97.     array <byte, 64> result;
  98.     auto ptr = result.begin();
  99.  
  100.     copy(sigma0.begin(), sigma0.end(), ptr);
  101.     advance(ptr, sigma0.size());
  102.  
  103.     copy(key.begin(), key.begin() + 16, ptr);
  104.     advance(ptr, 16);
  105.  
  106.     copy(sigma1.begin(), sigma1.end(), ptr);
  107.     advance(ptr, sigma1.size());
  108.  
  109.     copy(n.begin(), n.end(), ptr);
  110.     advance(ptr, n.size());
  111.  
  112.     copy(sigma2.begin(), sigma2.end(), ptr);
  113.     advance(ptr, sigma2.size());
  114.  
  115.     copy(key.begin() + 16, key.end(), ptr);
  116.     advance(ptr, 16);
  117.    
  118.     copy(sigma3.begin(), sigma3.end(), ptr);
  119.  
  120.     hash_func(result);
  121.     return result;
  122. }
  123.  
  124. // The Salsa20 encryption function
  125. vector <byte> encrypt(const vector <byte>& input, const array <byte, 32>& key, const array <byte, 8>& nonce) {
  126.     array <byte, 16> to_expand;
  127.     for (size_t i = 0; i < nonce.size(); i++) {
  128.         to_expand[i] = nonce[i];
  129.     }
  130.  
  131.     vector <byte> result(input.size());
  132.     array <byte, 64> expanded;
  133.     long long val = 0;
  134.     for (size_t i = 0; i < input.size(); i++) {
  135.         if (i % 64 == 0) {
  136.             long long val_copy = val++;
  137.             for (size_t j = 8; j < to_expand.size(); j++) {
  138.                 to_expand[j] = val_copy & BYTE_MASK;
  139.                 val_copy >>= 8;
  140.             }
  141.  
  142.             expanded = expansion_32(key, to_expand);
  143.         }
  144.  
  145.         result[i] = input[i] ^ expanded[i % 64];
  146.     }
  147.  
  148.     return result;
  149. }
  150.  
  151. int main() {
  152.     string hello_world = "asdasdasdsa";
  153.  
  154.     cout << "Original message" << endl;
  155.     cout << hello_world << endl;
  156.  
  157.     vector <byte> source(hello_world.size());
  158.     for (size_t i = 0; i < source.size(); i++) {
  159.         source[i] = hello_world[i];
  160.     }
  161.  
  162.     array <byte, 32> key;
  163.     for (int i = 0; i < 32; i++) {
  164.         key[i] = 100 + i;
  165.     }
  166.  
  167.     array <byte, 8> nonce;
  168.     for (int i = 0; i < 8; i++) {
  169.         nonce[i] = 200 + i;
  170.     }
  171.  
  172.     vector <byte> encrypted(encrypt(source, key, nonce));
  173.     vector <byte> decrypted(encrypt(encrypted, key, nonce));
  174.  
  175.     cout << "Source" << endl;
  176.     for (byte x : source) {
  177.         cout << (int)x << ' ';
  178.     }
  179.     cout << endl;
  180.  
  181.     cout << "Encrypted" << endl;
  182.     for (byte x : encrypted) {
  183.         cout << (int)x << ' ';
  184.     }
  185.     cout << endl;
  186.  
  187.     cout << "Decrypted" << endl;
  188.     for (byte x : decrypted) {
  189.         cout << (int)x << ' ';
  190.     }
  191.     cout << endl;
  192.  
  193.     return 0;
  194. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement