PRCYCoin  2.0.0.7rc1
P2P Digital Currency
chacha20.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 // Based on the public domain implementation 'merged' by D. J. Bernstein
6 // See https://cr.yp.to/chacha.html.
7 
8 #include "crypto/common.h"
9 #include "crypto/chacha20.h"
10 
11 #include <string.h>
12 
13 constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); }
14 
15 #define QUARTERROUND(a,b,c,d) \
16  a += b; d = rotl32(d ^ a, 16); \
17  c += d; b = rotl32(b ^ c, 12); \
18  a += b; d = rotl32(d ^ a, 8); \
19  c += d; b = rotl32(b ^ c, 7);
20 
21 static const unsigned char sigma[] = "expand 32-byte k";
22 static const unsigned char tau[] = "expand 16-byte k";
23 
24 void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
25 {
26  const unsigned char *constants;
27 
28  input[4] = ReadLE32(k + 0);
29  input[5] = ReadLE32(k + 4);
30  input[6] = ReadLE32(k + 8);
31  input[7] = ReadLE32(k + 12);
32  if (keylen == 32) { /* recommended */
33  k += 16;
34  constants = sigma;
35  } else { /* keylen == 16 */
36  constants = tau;
37  }
38  input[8] = ReadLE32(k + 0);
39  input[9] = ReadLE32(k + 4);
40  input[10] = ReadLE32(k + 8);
41  input[11] = ReadLE32(k + 12);
42  input[0] = ReadLE32(constants + 0);
43  input[1] = ReadLE32(constants + 4);
44  input[2] = ReadLE32(constants + 8);
45  input[3] = ReadLE32(constants + 12);
46  input[12] = 0;
47  input[13] = 0;
48  input[14] = 0;
49  input[15] = 0;
50 }
51 
53 {
54  memset(input, 0, sizeof(input));
55 }
56 
57 ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
58 {
59  SetKey(k, keylen);
60 }
61 
62 void ChaCha20::SetIV(uint64_t iv)
63 {
64  input[14] = iv;
65  input[15] = iv >> 32;
66 }
67 
68 void ChaCha20::Seek(uint64_t pos)
69 {
70  input[12] = pos;
71  input[13] = pos >> 32;
72 }
73 
74 void ChaCha20::Output(unsigned char* c, size_t bytes)
75 {
76  uint32_t x[16];
77  uint32_t j[16];
78  unsigned char *ctarget = nullptr;
79  unsigned char tmp[64];
80  unsigned int i;
81 
82  if (!bytes) return;
83 
84  for (uint32_t i=0; i<16; i++) {
85  j[i] = input[i];
86  }
87 
88  for (;;) {
89  if (bytes < 64) {
90  ctarget = c;
91  c = tmp;
92  }
93  for (uint32_t i=0; i<16; i++) {
94  x[i] = j[i];
95  }
96  for (i = 20;i > 0;i -= 2) {
97  QUARTERROUND( x[0], x[4], x[8],x[12])
98  QUARTERROUND( x[1], x[5], x[9],x[13])
99  QUARTERROUND( x[2], x[6],x[10],x[14])
100  QUARTERROUND( x[3], x[7],x[11],x[15])
101  QUARTERROUND( x[0], x[5],x[10],x[15])
102  QUARTERROUND( x[1], x[6],x[11],x[12])
103  QUARTERROUND( x[2], x[7], x[8],x[13])
104  QUARTERROUND( x[3], x[4], x[9],x[14])
105  }
106  for (uint32_t i=0; i<16; i++) {
107  x[i] += j[i];
108  }
109 
110  ++j[12];
111  if (!j[12]) ++j[13];
112 
113  for (uint32_t i=0; i<16; i++) {
114  WriteLE32(c + 4*i, x[i]);
115  }
116 
117  if (bytes <= 64) {
118  if (bytes < 64) {
119  for (i = 0;i < bytes;++i) ctarget[i] = c[i];
120  }
121  input[12] = j[12];
122  input[13] = j[13];
123  return;
124  }
125  bytes -= 64;
126  c += 64;
127  }
128 }
ChaCha20::SetKey
void SetKey(const unsigned char *key, size_t keylen)
Definition: chacha20.cpp:24
ChaCha20::Output
void Output(unsigned char *output, size_t bytes)
Definition: chacha20.cpp:74
chacha20.h
QUARTERROUND
#define QUARTERROUND(a, b, c, d)
Definition: chacha20.cpp:15
ChaCha20::Seek
void Seek(uint64_t pos)
Definition: chacha20.cpp:68
ChaCha20::input
uint32_t input[16]
Definition: chacha20.h:15
ChaCha20::ChaCha20
ChaCha20()
Definition: chacha20.cpp:52
ChaCha20::SetIV
void SetIV(uint64_t iv)
Definition: chacha20.cpp:62
common.h