Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CRYPTO_SPJSONWEBTOKEN_H_
25 : #define STAPPLER_CRYPTO_SPJSONWEBTOKEN_H_
26 :
27 : #include "SPCommon.h"
28 :
29 : #if MODULE_STAPPLER_DATA
30 :
31 : #include "SPString.h"
32 : #include "SPTime.h"
33 : #include "SPData.h"
34 : #include "SPDataWrapper.h"
35 : #include "SPCrypto.h"
36 :
37 : namespace STAPPLER_VERSIONIZED stappler {
38 :
39 : template <typename Interface>
40 : struct JsonWebToken {
41 : using String = typename Interface::StringType;
42 : using Bytes = typename Interface::BytesType;
43 : using Value = data::ValueTemplate<Interface>;
44 :
45 : enum SigAlg {
46 : None,
47 : HS256,
48 : HS512,
49 : RS256,
50 : RS512,
51 : ES256,
52 : ES512,
53 : GS256,
54 : GS512
55 : };
56 :
57 : static SigAlg getAlg(StringView);
58 : static StringView getAlgName(const SigAlg &);
59 :
60 : static JsonWebToken make(StringView iss, StringView aud, TimeInterval maxage = TimeInterval(), StringView sub = StringView());
61 :
62 : bool validate(StringView key) const;
63 : bool validate(BytesView key) const;
64 : bool validate(const crypto::PublicKey &key) const;
65 :
66 : bool validatePayload(StringView issuer, StringView aud) const;
67 : bool validatePayload() const;
68 :
69 : void setMaxAge(TimeInterval maxage);
70 :
71 : Value data() const;
72 :
73 : String exportPlain(data::EncodeFormat = data::EncodeFormat::Json) const;
74 :
75 : String exportSigned(SigAlg, StringView key,
76 : const CoderSource &passwd = CoderSource(), data::EncodeFormat = data::EncodeFormat::Json) const;
77 : String exportSigned(SigAlg, BytesView key,
78 : const CoderSource &passwd = CoderSource(), data::EncodeFormat = data::EncodeFormat::Json) const;
79 : String exportSigned(SigAlg, const crypto::PrivateKey &key, data::EncodeFormat = data::EncodeFormat::Json) const;
80 : String exportSigned(const crypto::PrivateKey &key, data::EncodeFormat = data::EncodeFormat::Json) const;
81 :
82 : JsonWebToken(Value &&payload, TimeInterval maxage = TimeInterval());
83 : JsonWebToken(const StringView &);
84 :
85 : String message;
86 : Value header;
87 : Value payload;
88 : Bytes sig;
89 :
90 : SigAlg alg = None;
91 : String kid;
92 : };
93 :
94 : template <typename Interface>
95 : class AesToken : public data::WrapperTemplate<Interface> {
96 : public:
97 : using String = typename Interface::StringType;
98 : using Bytes = typename Interface::BytesType;
99 : using Value = data::ValueTemplate<Interface>;
100 :
101 : template <typename T>
102 : using Function = typename Interface::template FunctionType<T>;
103 :
104 : struct Keys {
105 : crypto::PublicKey *pub;
106 : crypto::PrivateKey *priv;
107 : BytesView secret;
108 : };
109 :
110 : // struct to pass identity data to fingerprinting algorithm
111 : struct Fingerprint {
112 : crypto::HashFunction func = crypto::HashFunction::GOST_3411;
113 : BytesView fpb;
114 : Function<void(const crypto::HashCoderCallback &)> cb;
115 :
116 100 : Fingerprint(crypto::HashFunction fn, BytesView v) : func(fn), fpb(v) { }
117 100 : Fingerprint(crypto::HashFunction fn, Function<void(const crypto::HashCoderCallback &)> &&cb) : func(fn), cb(move(cb)) { }
118 : };
119 :
120 : // parse from JsonWebToken source
121 : static AesToken parse(StringView token, const Fingerprint &, StringView iss, StringView aud = StringView(), Keys = Keys());
122 :
123 : // parse from data::Value source
124 : static AesToken parse(const Value &, const Fingerprint &, Keys = Keys());
125 :
126 : static AesToken create(Keys = Keys());
127 :
128 : explicit operator bool () const;
129 :
130 : String exportToken(StringView iss, const Fingerprint &fpb, TimeInterval maxage, StringView sub) const;
131 : Value exportData(const Fingerprint &fpb) const;
132 :
133 : protected:
134 : static std::array<uint8_t, 64> getFingerprint(const Fingerprint &, Time t, BytesView secret);
135 :
136 : Bytes encryptAes(const crypto::BlockKey256 &, const Value &) const;
137 : static Value decryptAes(const crypto::BlockKey256 &, BytesView);
138 :
139 : AesToken();
140 : AesToken(Keys keys);
141 : AesToken(Value &&, Keys keys);
142 :
143 : Keys _keys;
144 : };
145 :
146 : template <typename Interface>
147 250 : auto JsonWebToken<Interface>::getAlg(StringView name) -> typename JsonWebToken<Interface>::SigAlg {
148 250 : if (name == "HS256") {
149 25 : return HS256;
150 225 : } else if (name == "HS512") {
151 25 : return HS512;
152 200 : } else if (name == "RS256") {
153 25 : return RS256;
154 175 : } else if (name == "RS512") {
155 25 : return RS512;
156 150 : } else if (name == "ES256") {
157 25 : return ES256;
158 125 : } else if (name == "ES512") {
159 25 : return ES512;
160 100 : } else if (name == "GS256") {
161 50 : return GS256;
162 50 : } else if (name == "GS512") {
163 50 : return GS512;
164 : }
165 0 : return JsonWebToken::None;
166 : }
167 :
168 : template <typename Interface>
169 375 : StringView JsonWebToken<Interface>::getAlgName(const SigAlg &alg) {
170 375 : switch (alg) {
171 0 : case None: return "none"; break;
172 50 : case HS256: return "HS256"; break;
173 50 : case HS512: return "HS512"; break;
174 25 : case RS256: return "RS256"; break;
175 50 : case RS512: return "RS512"; break;
176 25 : case ES256: return "ES256"; break;
177 25 : case ES512: return "ES512"; break;
178 100 : case GS256: return "GS256"; break;
179 50 : case GS512: return "GS512"; break;
180 : }
181 0 : return StringView();
182 : }
183 :
184 : template <typename Interface>
185 75 : JsonWebToken<Interface> JsonWebToken<Interface>::make(StringView iss, StringView aud, TimeInterval maxage, StringView sub) {
186 75 : Value payload;
187 75 : payload.setString(iss, "iss");
188 75 : if (!sub.empty()) {
189 75 : payload.setString(sub, "sub");
190 : }
191 :
192 75 : if (!aud.empty()) {
193 75 : payload.setString(aud, "aud");
194 : }
195 :
196 150 : return JsonWebToken(move(payload), maxage);
197 75 : }
198 :
199 : template <typename Interface>
200 175 : JsonWebToken<Interface>::JsonWebToken(Value &&val, TimeInterval maxage) : payload(move(val)) {
201 175 : if (maxage != nullptr) {
202 75 : payload.setInteger((Time::now() + maxage).toSeconds(), "exp");
203 : }
204 175 : }
205 :
206 : template <typename Interface>
207 250 : JsonWebToken<Interface>::JsonWebToken(const StringView &token) {
208 250 : StringView r(token);
209 250 : auto head = r.readUntil<StringView::Chars<'.'>>();
210 250 : if (r.is('.')) {
211 250 : ++ r;
212 : }
213 :
214 250 : header = data::read<Interface>(base64::decode<Interface>(head));
215 500 : for (auto &it : header.asDict()) {
216 250 : if (it.first == "alg") {
217 250 : alg = getAlg(it.second.getString());
218 0 : } else if (it.first == "kid") {
219 0 : kid = it.second.asString();
220 : }
221 : }
222 :
223 250 : auto pl = r.readUntil<StringView::Chars<'.'>>();
224 :
225 250 : message = String(token.data(), token.size() - r.size());
226 :
227 250 : if (r.is('.')) {
228 250 : ++ r;
229 : }
230 :
231 250 : payload = data::read<Interface>(base64::decode<Interface>(pl));
232 250 : sig = base64::decode<Interface>(r);
233 250 : }
234 :
235 : template <typename Interface>
236 : void JsonWebToken<Interface>::setMaxAge(TimeInterval maxage) {
237 : payload.setInteger((Time::now() + maxage).toSeconds(), "exp");
238 : }
239 :
240 : template <typename Interface>
241 50 : bool JsonWebToken<Interface>::validate(StringView key) const {
242 50 : return validate(BytesView((const uint8_t *)key.data(), key.size() + 1));
243 : }
244 :
245 : template <typename Interface>
246 100 : bool JsonWebToken<Interface>::validate(BytesView key) const {
247 100 : if (key.empty()) {
248 0 : return false;
249 : }
250 :
251 100 : switch (alg) {
252 25 : case HS256: {
253 25 : auto keySig = string::Sha256::hmac(message, key);
254 25 : if (sig.size() == keySig.size() && memcmp(sig.data(), keySig.data(), sig.size()) == 0) {
255 25 : return true;
256 : }
257 0 : break;
258 : }
259 25 : case HS512: {
260 25 : auto keySig = string::Sha512::hmac(message, key);
261 25 : if (sig.size() == keySig.size() && memcmp(sig.data(), keySig.data(), sig.size()) == 0) {
262 25 : return true;
263 : }
264 0 : break;
265 : }
266 50 : default: {
267 50 : crypto::PublicKey pk(key);
268 :
269 50 : if (pk) {
270 50 : return validate(pk);
271 : }
272 0 : break;
273 50 : }
274 : }
275 :
276 0 : return false;
277 : }
278 :
279 : template <typename Interface>
280 200 : bool JsonWebToken<Interface>::validate(const crypto::PublicKey &pk) const {
281 200 : if (!pk) {
282 0 : return false;
283 : }
284 :
285 200 : crypto::SignAlgorithm algo = crypto::SignAlgorithm::RSA_SHA512;
286 200 : switch (alg) {
287 25 : case RS256: algo = crypto::SignAlgorithm::RSA_SHA256; break;
288 25 : case ES256: algo = crypto::SignAlgorithm::ECDSA_SHA256; break;
289 50 : case GS256: algo = crypto::SignAlgorithm::GOST_256; break;
290 25 : case RS512: algo = crypto::SignAlgorithm::RSA_SHA512; break;
291 25 : case ES512: algo = crypto::SignAlgorithm::ECDSA_SHA512; break;
292 50 : case GS512: algo = crypto::SignAlgorithm::GOST_512; break;
293 0 : default: return false; break;
294 : }
295 :
296 200 : if (pk.verify(BytesView((const uint8_t *)message.data(), message.size()), sig, algo)) {
297 200 : return true;
298 : }
299 :
300 0 : return false;
301 : }
302 :
303 : template <typename Interface>
304 50 : bool JsonWebToken<Interface>::validatePayload(StringView issuer, StringView aud) const {
305 50 : auto exp = payload.getInteger("exp");
306 100 : if (issuer == payload.getString("iss") && aud == payload.getString("aud")
307 100 : && (exp == 0 || exp > int64_t(Time::now().toSeconds()))) {
308 50 : return true;
309 : }
310 0 : return false;
311 : }
312 :
313 : template <typename Interface>
314 : bool JsonWebToken<Interface>::validatePayload() const {
315 : auto exp = payload.getInteger("exp");
316 : if (exp == 0 || exp > int64_t(Time::now().toSeconds())) {
317 : return true;
318 : }
319 : return false;
320 : }
321 :
322 : template <typename Interface>
323 : auto JsonWebToken<Interface>::data() const -> Value {
324 : Value data;
325 : data.setValue(header, "header");
326 : data.setValue(payload, "payload");
327 : data.setBytes(sig, "sig");
328 : return data;
329 : }
330 :
331 : template <typename Interface>
332 : auto JsonWebToken<Interface>::exportPlain(data::EncodeFormat format) const -> String {
333 : return string::toString<Interface>(
334 : base64url::encode(data::write(header, format)), ".", base64url::encode(data::write(payload, format)));
335 : }
336 :
337 : template <typename Interface>
338 50 : auto JsonWebToken<Interface>::exportSigned(SigAlg alg, StringView key,
339 : const CoderSource &passwd, data::EncodeFormat format) const -> String {
340 50 : return exportSigned(alg, BytesView((const uint8_t *)key.data(), key.size()), passwd, format);
341 : }
342 :
343 : template <typename Interface>
344 150 : auto JsonWebToken<Interface>::exportSigned(SigAlg alg, BytesView key,
345 : const CoderSource &passwd, data::EncodeFormat format) const -> String {
346 :
347 150 : switch (alg) {
348 50 : case HS256: {
349 50 : Value hederData(header);
350 50 : hederData.setString(getAlgName(alg), "alg");
351 :
352 150 : auto data = string::toString<Interface>(
353 : base64url::encode<Interface>(data::write<Interface>(hederData, format)),
354 50 : ".", base64url::encode<Interface>(data::write<Interface>(payload, format)));
355 :
356 : return string::toString<Interface>(
357 50 : data, ".", base64url::encode<Interface>(string::Sha256::hmac(data, key)));
358 : break;
359 50 : }
360 50 : case HS512: {
361 50 : Value hederData(header);
362 50 : hederData.setString(getAlgName(alg), "alg");
363 :
364 150 : auto data = string::toString<Interface>(
365 : base64url::encode<Interface>(data::write<Interface>(hederData, format)),
366 50 : ".", base64url::encode<Interface>(data::write<Interface>(payload, format)));
367 :
368 : return string::toString<Interface>(
369 50 : data, ".", base64url::encode<Interface>(string::Sha512::hmac(data, key)));
370 : break;
371 50 : }
372 50 : default: {
373 50 : crypto::PrivateKey pk(key, passwd);
374 50 : if (pk) {
375 50 : return exportSigned(alg, pk, format);
376 : }
377 50 : }
378 : }
379 :
380 0 : return String();
381 : }
382 :
383 : template <typename Interface>
384 275 : auto JsonWebToken<Interface>::exportSigned(SigAlg alg, const crypto::PrivateKey &pk, data::EncodeFormat format) const -> String {
385 275 : if (!pk) {
386 0 : return String();
387 : }
388 :
389 275 : Value hederData(header);
390 275 : hederData.setString(getAlgName(alg), "alg");
391 :
392 825 : auto data = string::toString<Interface>(
393 : base64url::encode<Interface>(data::write<Interface>(hederData, format)),
394 275 : ".", base64url::encode<Interface>(data::write<Interface>(payload, format)));
395 :
396 275 : crypto::SignAlgorithm algo = crypto::SignAlgorithm::RSA_SHA512;
397 275 : switch (alg) {
398 25 : case RS256: algo = crypto::SignAlgorithm::RSA_SHA256; break;
399 25 : case ES256: algo = crypto::SignAlgorithm::ECDSA_SHA256; break;
400 100 : case GS256: algo = crypto::SignAlgorithm::GOST_256; break;
401 50 : case RS512: algo = crypto::SignAlgorithm::RSA_SHA512; break;
402 25 : case ES512: algo = crypto::SignAlgorithm::ECDSA_SHA512; break;
403 50 : case GS512: algo = crypto::SignAlgorithm::GOST_512; break;
404 0 : default: break;
405 : }
406 :
407 275 : if (pk.sign([&] (BytesView sign) {
408 275 : data = string::toString<Interface>(data, ".", base64url::encode<Interface>(sign));
409 : }, data, algo)) {
410 275 : return data;
411 : }
412 :
413 0 : return String();
414 275 : }
415 :
416 : template <typename Interface>
417 200 : auto JsonWebToken<Interface>::exportSigned(const crypto::PrivateKey &key, data::EncodeFormat fmt) const -> String {
418 200 : switch (key.getType()) {
419 25 : case crypto::KeyType::RSA:
420 25 : return exportSigned(RS512, key, fmt);
421 : break;
422 25 : case crypto::KeyType::ECDSA:
423 : case crypto::KeyType::EDDSA_ED448:
424 25 : return exportSigned(ES512, key, fmt);
425 : break;
426 100 : case crypto::KeyType::GOST3410_2012_256:
427 100 : return exportSigned(GS256, key, fmt);
428 : break;
429 50 : case crypto::KeyType::GOST3410_2012_512:
430 50 : return exportSigned(GS512, key, fmt);
431 : break;
432 0 : default:
433 0 : break;
434 : }
435 0 : return String();
436 : }
437 :
438 : template <typename Interface>
439 50 : AesToken<Interface> AesToken<Interface>::parse(StringView token, const Fingerprint &fpb, StringView iss, StringView aud, Keys keys) {
440 50 : if (aud.empty()) {
441 0 : aud = iss;
442 : }
443 :
444 50 : JsonWebToken<Interface> input(token);
445 50 : if (input.validate(*keys.pub) && input.validatePayload(iss, aud)) {
446 50 : Time tf = Time::microseconds(input.payload.getInteger("tf"));
447 50 : auto fp = getFingerprint(fpb, tf, keys.secret);
448 :
449 50 : if (BytesView(fp.data(), fp.size()) == BytesView(input.payload.getBytes("fp"))) {
450 50 : auto v = crypto::getBlockInfo(input.payload.getBytes("p"));
451 50 : crypto::BlockKey256 aesKey;
452 50 : if (keys.priv) {
453 50 : aesKey = crypto::makeBlockKey(*keys.priv, BytesView(fp.data(), fp.size()), v.cipher, v.version);
454 : } else {
455 0 : aesKey = crypto::makeBlockKey(keys.secret, BytesView(fp.data(), fp.size()), v.cipher, v.version);
456 : }
457 :
458 50 : auto p = decryptAes(aesKey, input.payload.getBytes("p"));
459 50 : if (p) {
460 50 : return AesToken(move(p), keys);
461 : }
462 50 : }
463 : }
464 0 : return AesToken();
465 50 : }
466 :
467 : template <typename Interface>
468 75 : AesToken<Interface> AesToken<Interface>::parse(const Value &payload, const Fingerprint &fpb, Keys keys) {
469 75 : Time tf = Time::microseconds(payload.getInteger("tf"));
470 75 : auto fp = getFingerprint(fpb, tf, keys.secret);
471 :
472 75 : if (BytesView(fp.data(), fp.size()) == BytesView(payload.getBytes("fp"))) {
473 75 : auto v = crypto::getBlockInfo(payload.getBytes("p"));
474 :
475 75 : crypto::BlockKey256 aesKey;
476 75 : if (keys.priv) {
477 75 : aesKey = crypto::makeBlockKey(*keys.priv, BytesView(fp.data(), fp.size()), v.cipher, v.version);
478 : } else {
479 0 : aesKey = crypto::makeBlockKey(keys.secret, BytesView(fp.data(), fp.size()), v.cipher, v.version);
480 : }
481 :
482 75 : auto p = decryptAes(aesKey, payload.getBytes("p"));
483 75 : if (p) {
484 75 : return AesToken(move(p), keys);
485 : }
486 75 : }
487 0 : return AesToken();
488 : }
489 :
490 : template <typename Interface>
491 75 : AesToken<Interface> AesToken<Interface>::create(Keys keys) {
492 75 : return AesToken(keys);
493 : }
494 :
495 : template <typename Interface>
496 25 : AesToken<Interface>::operator bool () const {
497 25 : return !this->_data.isNull() && _keys.priv && *_keys.priv && !_keys.secret.empty();
498 : }
499 :
500 : template <typename Interface>
501 75 : auto AesToken<Interface>::exportToken(StringView iss, const Fingerprint &fpb, TimeInterval maxage, StringView sub) const -> String {
502 75 : auto t = Time::now();
503 :
504 75 : JsonWebToken<Interface> token = JsonWebToken<Interface>::make(iss, iss, maxage, sub);
505 75 : auto fp = getFingerprint(fpb, t, _keys.secret);
506 :
507 75 : token.payload.setBytes(BytesView(fp.data(), fp.size()), "fp");
508 75 : token.payload.setInteger(t.toMicros(), "tf");
509 :
510 75 : crypto::BlockKey256 aesKey;
511 75 : if (_keys.priv) {
512 75 : switch (_keys.priv->getType()) {
513 50 : case crypto::KeyType::GOST3410_2012_256:
514 : case crypto::KeyType::GOST3410_2012_512:
515 50 : aesKey = crypto::makeBlockKey(*_keys.priv, BytesView(fp.data(), fp.size()), crypto::BlockCipher::Gost3412_2015_CTR_ACPKM);
516 50 : break;
517 25 : default:
518 25 : aesKey = crypto::makeBlockKey(*_keys.priv, BytesView(fp.data(), fp.size()));
519 25 : break;
520 : }
521 : } else {
522 0 : aesKey = crypto::makeBlockKey(_keys.secret, BytesView(fp.data(), fp.size()));
523 : }
524 :
525 75 : token.payload.setBytes(encryptAes(aesKey, this->_data), "p");
526 150 : return token.exportSigned(*_keys.priv, data::EncodeFormat::Cbor);
527 75 : }
528 :
529 : template <typename Interface>
530 200 : auto AesToken<Interface>::exportData(const Fingerprint &fpb) const -> Value {
531 200 : auto t = Time::now();
532 200 : auto fp = getFingerprint(fpb, t, _keys.secret);
533 :
534 200 : Value payload;
535 200 : payload.setBytes(BytesView(fp.data(), fp.size()), "fp");
536 200 : payload.setInteger(t.toMicros(), "tf");
537 :
538 200 : crypto::BlockKey256 aesKey;
539 200 : if (_keys.priv) {
540 200 : switch (_keys.priv->getType()) {
541 50 : case crypto::KeyType::GOST3410_2012_256:
542 : case crypto::KeyType::GOST3410_2012_512:
543 50 : aesKey = crypto::makeBlockKey(*_keys.priv, BytesView(fp.data(), fp.size()), crypto::BlockCipher::Gost3412_2015_CTR_ACPKM);
544 50 : break;
545 150 : default:
546 150 : aesKey = crypto::makeBlockKey(*_keys.priv, BytesView(fp.data(), fp.size()));
547 150 : break;
548 : }
549 : } else {
550 0 : aesKey = crypto::makeBlockKey(_keys.secret, BytesView(fp.data(), fp.size()));
551 : }
552 :
553 200 : payload.setBytes(encryptAes(aesKey, this->_data), "p");
554 400 : return payload;
555 0 : }
556 :
557 : template <typename Interface>
558 400 : std::array<uint8_t, 64> AesToken<Interface>::getFingerprint(const Fingerprint &fp, Time t, BytesView secret) {
559 400 : auto v = byteorder::HostToBig(t.toMicros());
560 400 : if (!fp.fpb.empty()) {
561 300 : switch (fp.func) {
562 25 : case crypto::HashFunction::SHA_2:
563 25 : return crypto::Sha512().update(secret).update(fp.fpb).update(CoderSource((const uint8_t *)&v, sizeof(v))) .final();
564 : break;
565 275 : case crypto::HashFunction::GOST_3411:
566 275 : return crypto::Gost3411_512().update(secret).update(fp.fpb).update(CoderSource((const uint8_t *)&v, sizeof(v))) .final();
567 : break;
568 : }
569 100 : } else if (fp.cb) {
570 100 : return crypto::hash512([&] (const crypto::HashCoderCallback &cb) {
571 50 : fp.cb(cb);
572 100 : }, fp.func);
573 : } else {
574 50 : switch (fp.func) {
575 25 : case crypto::HashFunction::SHA_2:
576 25 : return crypto::Sha512().update(secret).update(CoderSource((const uint8_t *)&v, sizeof(v))).final();
577 : break;
578 25 : case crypto::HashFunction::GOST_3411:
579 25 : return crypto::Gost3411_512().update(secret).update(CoderSource((const uint8_t *)&v, sizeof(v))).final();
580 : break;
581 : }
582 : }
583 0 : return std::array<uint8_t, 64>();
584 : }
585 :
586 : template <typename Interface>
587 275 : auto AesToken<Interface>::encryptAes(const crypto::BlockKey256 &key, const Value &val) const -> Bytes {
588 275 : auto d = data::write<Interface>(val, data::EncodeFormat::CborCompressed);
589 275 : Bytes out;
590 275 : crypto::encryptBlock(key, d, [&] (BytesView data) {
591 275 : out = data.bytes<Interface>();
592 : });
593 550 : return out;
594 275 : }
595 :
596 : template <typename Interface>
597 125 : auto AesToken<Interface>::decryptAes(const crypto::BlockKey256 &key, BytesView val) -> Value {
598 125 : Value out;
599 125 : crypto::decryptBlock(key, val, [&] (BytesView data) {
600 125 : out = data::read<Interface>(data);
601 : });
602 125 : return out;
603 0 : }
604 :
605 : template <typename Interface>
606 0 : AesToken<Interface>::AesToken() { }
607 :
608 : template <typename Interface>
609 75 : AesToken<Interface>::AesToken(Keys keys) : _keys(keys) { }
610 :
611 : template <typename Interface>
612 125 : AesToken<Interface>::AesToken(Value &&v, Keys keys) : data::WrapperTemplate<Interface>(std::move(v)), _keys(keys) { }
613 :
614 : }
615 :
616 : #else
617 :
618 : #warning "Enable module stappler_data to use JsonWebToken"
619 :
620 : #endif // MODULE_STAPPLER_DATA
621 :
622 : #endif /* STAPPLER_CRYPTO_SPJSONWEBTOKEN_H_ */
|