| 1 | #include"keyops.h"
|
|---|
| 2 |
|
|---|
| 3 | #include"../util/bytestream.h"
|
|---|
| 4 | #include"../util/base64.h"
|
|---|
| 5 | #include"../util/sha1.h"
|
|---|
| 6 |
|
|---|
| 7 | bool sym_encrypt(const QByteArray &data, const Cipher::Key &key, const QByteArray &iv, QString *out)
|
|---|
| 8 | {
|
|---|
| 9 | QByteArray encData = iv.copy();
|
|---|
| 10 | bool ok;
|
|---|
| 11 | QByteArray a = Cipher::encrypt(data, key, iv, true, &ok);
|
|---|
| 12 | if(!ok)
|
|---|
| 13 | return false;
|
|---|
| 14 | ByteStream::appendArray(&encData, a);
|
|---|
| 15 |
|
|---|
| 16 | *out = Base64::arrayToString(encData);
|
|---|
| 17 | return true;
|
|---|
| 18 | }
|
|---|
| 19 |
|
|---|
| 20 | bool sym_decrypt(const QString &str, const Cipher::Key &key, QByteArray *out)
|
|---|
| 21 | {
|
|---|
| 22 | QByteArray data = Base64::stringToArray(str);
|
|---|
| 23 | int r = Cipher::ivSize(key.type());
|
|---|
| 24 | if(r == -1)
|
|---|
| 25 | return false;
|
|---|
| 26 | if((int)data.size() < r)
|
|---|
| 27 | return false;
|
|---|
| 28 | QByteArray iv = ByteStream::takeArray(&data, r);
|
|---|
| 29 | bool ok;
|
|---|
| 30 | QByteArray result = Cipher::decrypt(data, key, iv, true, &ok);
|
|---|
| 31 | if(!ok)
|
|---|
| 32 | return false;
|
|---|
| 33 |
|
|---|
| 34 | *out = result;
|
|---|
| 35 | return true;
|
|---|
| 36 | }
|
|---|
| 37 |
|
|---|
| 38 | static QByteArray calcCMS(const QByteArray &key)
|
|---|
| 39 | {
|
|---|
| 40 | QByteArray a = SHA1::hash(key);
|
|---|
| 41 | a.resize(8);
|
|---|
| 42 | return a;
|
|---|
| 43 | }
|
|---|
| 44 |
|
|---|
| 45 | unsigned char sym_3des_fixed_iv[8] = { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 };
|
|---|
| 46 | unsigned char sym_aes_fixed_val[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
|
|---|
| 47 |
|
|---|
| 48 | static QByteArray cat64(const QByteArray &a1, const QByteArray &a2)
|
|---|
| 49 | {
|
|---|
| 50 | QByteArray out = a1.copy();
|
|---|
| 51 | ByteStream::appendArray(&out, a2);
|
|---|
| 52 | return out;
|
|---|
| 53 | }
|
|---|
| 54 |
|
|---|
| 55 | static QByteArray xor64(const QByteArray &a1, const QByteArray &a2)
|
|---|
| 56 | {
|
|---|
| 57 | QByteArray out(a1.size());
|
|---|
| 58 | for(uint n = 0; n < a1.size(); ++n)
|
|---|
| 59 | out[n] = a1[n] ^ a2[n];
|
|---|
| 60 | return out;
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | static QByteArray msb64(const QByteArray &a)
|
|---|
| 64 | {
|
|---|
| 65 | QByteArray out(8);
|
|---|
| 66 | for(uint n = 0; n < 8; ++n)
|
|---|
| 67 | out[n] = a[n];
|
|---|
| 68 | return out;
|
|---|
| 69 | }
|
|---|
| 70 |
|
|---|
| 71 | static QByteArray lsb64(const QByteArray &a)
|
|---|
| 72 | {
|
|---|
| 73 | QByteArray out(8);
|
|---|
| 74 | for(uint n = 0; n < 8; ++n)
|
|---|
| 75 | out[n] = a[n+8];
|
|---|
| 76 | return out;
|
|---|
| 77 | }
|
|---|
| 78 |
|
|---|
| 79 | static QByteArray get64(const QByteArray &from, uint x)
|
|---|
| 80 | {
|
|---|
| 81 | QByteArray out(8);
|
|---|
| 82 | int base = (x-1) * 8;
|
|---|
| 83 | for(uint n = 0; n < 8; ++n)
|
|---|
| 84 | out[n] = from[base+n];
|
|---|
| 85 | return out;
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | static void set64(QByteArray *from, uint x, const QByteArray &a)
|
|---|
| 89 | {
|
|---|
| 90 | int base = (x-1) * 8;
|
|---|
| 91 | for(uint n = 0; n < 8; ++n)
|
|---|
| 92 | (*from)[base+n] = a[n];
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | static QByteArray uintTo64(uint x)
|
|---|
| 96 | {
|
|---|
| 97 | QByteArray out(8);
|
|---|
| 98 | out[0] = 0x00;
|
|---|
| 99 | out[1] = 0x00;
|
|---|
| 100 | out[2] = 0x00;
|
|---|
| 101 | out[3] = 0x00;
|
|---|
| 102 | out[4] = (x >> 24) & 0xff;
|
|---|
| 103 | out[5] = (x >> 16) & 0xff;
|
|---|
| 104 | out[6] = (x >> 8) & 0xff;
|
|---|
| 105 | out[7] = (x >> 0) & 0xff;
|
|---|
| 106 | return out;
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | bool sym_keywrap(const QByteArray &data, const Cipher::Key &key, QString *out)
|
|---|
| 110 | {
|
|---|
| 111 | int x = key.type();
|
|---|
| 112 | if(x == Cipher::TripleDES) {
|
|---|
| 113 | QByteArray cks = calcCMS(data);
|
|---|
| 114 | QByteArray wkcks = data.copy();
|
|---|
| 115 | ByteStream::appendArray(&wkcks, cks);
|
|---|
| 116 | QByteArray iv = Cipher::generateIV(key.type());
|
|---|
| 117 | bool ok;
|
|---|
| 118 | QByteArray temp1 = Cipher::encrypt(wkcks, key, iv, false, &ok);
|
|---|
| 119 | if(!ok)
|
|---|
| 120 | return false;
|
|---|
| 121 | QByteArray temp2 = iv;
|
|---|
| 122 | ByteStream::appendArray(&temp2, temp1);
|
|---|
| 123 | QByteArray temp3(temp2.size());
|
|---|
| 124 | int n2 = (int)temp2.size()-1;
|
|---|
| 125 | for(int n = 0; n < (int)temp2.size(); ++n)
|
|---|
| 126 | temp3[n2--] = temp2[n];
|
|---|
| 127 | memcpy(iv.data(), sym_3des_fixed_iv, 8);
|
|---|
| 128 | QByteArray final = Cipher::encrypt(temp3, key, iv, false, &ok);
|
|---|
| 129 | if(!ok)
|
|---|
| 130 | return false;
|
|---|
| 131 |
|
|---|
| 132 | *out = Base64::arrayToString(final);
|
|---|
| 133 | return true;
|
|---|
| 134 | }
|
|---|
| 135 | else if(x == Cipher::AES_128 || x == Cipher::AES_256) {
|
|---|
| 136 | QByteArray c;
|
|---|
| 137 | QByteArray work = data.copy();
|
|---|
| 138 | int n = work.size() / 8;
|
|---|
| 139 | if(work.size() % 8)
|
|---|
| 140 | return false;
|
|---|
| 141 | if(n < 1)
|
|---|
| 142 | return false;
|
|---|
| 143 |
|
|---|
| 144 | if(n == 1) {
|
|---|
| 145 | QByteArray val(8);
|
|---|
| 146 | memcpy(val.data(), sym_aes_fixed_val, 8);
|
|---|
| 147 | bool ok;
|
|---|
| 148 | c = Cipher::encrypt(cat64(val, work), key, QByteArray(), false, &ok);
|
|---|
| 149 | if(!ok)
|
|---|
| 150 | return false;
|
|---|
| 151 | }
|
|---|
| 152 | else {
|
|---|
| 153 | QByteArray r = work;
|
|---|
| 154 | QByteArray a(8);
|
|---|
| 155 | memcpy(a.data(), sym_aes_fixed_val, 8);
|
|---|
| 156 |
|
|---|
| 157 | for(int j = 0; j <= 5; ++j) {
|
|---|
| 158 | for(int i = 1; i <= n; ++i) {
|
|---|
| 159 | uint t = i + (j * n);
|
|---|
| 160 | bool ok;
|
|---|
| 161 | QByteArray b = Cipher::encrypt(cat64(a, get64(r, i)), key, QByteArray(), false, &ok);
|
|---|
| 162 | if(!ok)
|
|---|
| 163 | return false;
|
|---|
| 164 | a = xor64(uintTo64(t), msb64(b));
|
|---|
| 165 | set64(&r, i, lsb64(b));
|
|---|
| 166 | }
|
|---|
| 167 | }
|
|---|
| 168 |
|
|---|
| 169 | c = a;
|
|---|
| 170 | ByteStream::appendArray(&c, r);
|
|---|
| 171 | }
|
|---|
| 172 |
|
|---|
| 173 | *out = Base64::arrayToString(c);
|
|---|
| 174 | return true;
|
|---|
| 175 | }
|
|---|
| 176 |
|
|---|
| 177 | return false;
|
|---|
| 178 | }
|
|---|
| 179 |
|
|---|
| 180 | bool sym_keyunwrap(const QString &str, const Cipher::Key &key, QByteArray *out)
|
|---|
| 181 | {
|
|---|
| 182 | int x = key.type();
|
|---|
| 183 | QByteArray data = Base64::stringToArray(str);
|
|---|
| 184 | if(x == Cipher::TripleDES) {
|
|---|
| 185 | QByteArray iv(8);
|
|---|
| 186 | memcpy(iv.data(), sym_3des_fixed_iv, 8);
|
|---|
| 187 | bool ok;
|
|---|
| 188 | QByteArray temp3 = Cipher::decrypt(data, key, iv, false, &ok);
|
|---|
| 189 | if(!ok)
|
|---|
| 190 | return false;
|
|---|
| 191 | QByteArray temp2(temp3.size());
|
|---|
| 192 | int n2 = (int)temp3.size()-1;
|
|---|
| 193 | for(int n = 0; n < (int)temp3.size(); ++n)
|
|---|
| 194 | temp2[n2--] = temp3[n];
|
|---|
| 195 | if((int)temp2.size() < 8)
|
|---|
| 196 | return false;
|
|---|
| 197 | iv = ByteStream::takeArray(&temp2, 8);
|
|---|
| 198 | QByteArray temp1 = temp2;
|
|---|
| 199 | QByteArray wkcks = Cipher::decrypt(temp1, key, iv, false, &ok);
|
|---|
| 200 | if(!ok)
|
|---|
| 201 | return false;
|
|---|
| 202 | if((int)wkcks.size() < 8)
|
|---|
| 203 | return false;
|
|---|
| 204 | QByteArray wk = ByteStream::takeArray(&wkcks, wkcks.size() - 8);
|
|---|
| 205 | QByteArray cks = wkcks;
|
|---|
| 206 | QByteArray t = calcCMS(wk);
|
|---|
| 207 |
|
|---|
| 208 | if(cks.size() != t.size())
|
|---|
| 209 | return false;
|
|---|
| 210 | for(int n = 0; n < (int)t.size(); ++n) {
|
|---|
| 211 | if(t[n] != cks[n])
|
|---|
| 212 | return false;
|
|---|
| 213 | }
|
|---|
| 214 | *out = wk;
|
|---|
| 215 | return true;
|
|---|
| 216 | }
|
|---|
| 217 | else if(x == Cipher::AES_128 || x == Cipher::AES_256) {
|
|---|
| 218 | QByteArray p;
|
|---|
| 219 | QByteArray work = data.copy();
|
|---|
| 220 | if(work.size() % 8)
|
|---|
| 221 | return false;
|
|---|
| 222 | int n = (work.size() / 8) - 1;
|
|---|
| 223 | if(n < 1)
|
|---|
| 224 | return false;
|
|---|
| 225 |
|
|---|
| 226 | QByteArray a;
|
|---|
| 227 | if(n == 1) {
|
|---|
| 228 | bool ok;
|
|---|
| 229 | QByteArray b = Cipher::decrypt(work, key, QByteArray(), false, &ok);
|
|---|
| 230 | if(!ok)
|
|---|
| 231 | return false;
|
|---|
| 232 | ByteStream::appendArray(&p, lsb64(b));
|
|---|
| 233 | a = msb64(b);
|
|---|
| 234 | }
|
|---|
| 235 | else {
|
|---|
| 236 | a = ByteStream::takeArray(&work, 8);
|
|---|
| 237 | QByteArray r = work;
|
|---|
| 238 | for(int j = 5; j >= 0; --j) {
|
|---|
| 239 | for(int i = n; i >= 1; --i) {
|
|---|
| 240 | uint t = i + (j * n);
|
|---|
| 241 | QByteArray ta = xor64(uintTo64(t), a);
|
|---|
| 242 | bool ok;
|
|---|
| 243 | QByteArray b = Cipher::decrypt(cat64(ta, get64(r, i)), key, QByteArray(), false, &ok);
|
|---|
| 244 | if(!ok)
|
|---|
| 245 | return false;
|
|---|
| 246 | a = msb64(b);
|
|---|
| 247 | set64(&r, i, lsb64(b));
|
|---|
| 248 | }
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 | p = r;
|
|---|
| 252 | }
|
|---|
| 253 |
|
|---|
| 254 | for(int i = 0; i < 8; ++i) {
|
|---|
| 255 | if((unsigned char)a[i] != sym_aes_fixed_val[i])
|
|---|
| 256 | return false;
|
|---|
| 257 | }
|
|---|
| 258 |
|
|---|
| 259 | *out = p;
|
|---|
| 260 | return true;
|
|---|
| 261 | }
|
|---|
| 262 |
|
|---|
| 263 | return false;
|
|---|
| 264 | }
|
|---|