source: psi/trunk/cutestuff/xmlsec/keyops.cpp@ 59

Last change on this file since 59 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 5.9 KB
Line 
1#include"keyops.h"
2
3#include"../util/bytestream.h"
4#include"../util/base64.h"
5#include"../util/sha1.h"
6
7bool 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
20bool 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
38static QByteArray calcCMS(const QByteArray &key)
39{
40 QByteArray a = SHA1::hash(key);
41 a.resize(8);
42 return a;
43}
44
45unsigned char sym_3des_fixed_iv[8] = { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 };
46unsigned char sym_aes_fixed_val[8] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
47
48static QByteArray cat64(const QByteArray &a1, const QByteArray &a2)
49{
50 QByteArray out = a1.copy();
51 ByteStream::appendArray(&out, a2);
52 return out;
53}
54
55static 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
63static 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
71static 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
79static 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
88static 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
95static 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
109bool 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
180bool 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}
Note: See TracBrowser for help on using the repository browser.