#include <boost/test/included/unit_test.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/crypto/public_key.hpp>
#include <fc/crypto/private_key.hpp>
#include <fc/crypto/signature.hpp>
#include <fc/utility.hpp>
Go to the source code of this file.
◆ BOOST_TEST_MODULE
#define BOOST_TEST_MODULE webauthn_test_mod |
◆ BOOST_AUTO_TEST_CASE() [1/26]
BOOST_AUTO_TEST_CASE |
( |
auth_data_rpid_hash_bad | | ) |
|
Definition at line 199 of file test_webauthn.cpp.
199 {
200 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
202
203 std::vector<uint8_t> auth_data(37);
205 memcpy(auth_data.data(), origin_hash_corrupt.
data(),
sizeof(origin_hash_corrupt));
206 auth_data[4]++;
207
208 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
209 return e.to_detail_string().find("webauthn rpid hash doesn't match origin") != std::string::npos;
210 });
static sha256 hash(const char *d, uint32_t dlen)
const char * data() const
std::string base64url_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
memcpy((char *) pInfo->slotDescription, s, l)
◆ BOOST_AUTO_TEST_CASE() [2/26]
BOOST_AUTO_TEST_CASE |
( |
auth_data_too_short | | ) |
|
Definition at line 214 of file test_webauthn.cpp.
214 {
215 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
217
218 std::vector<uint8_t> auth_data(1);
219
220 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
221 return e.to_detail_string().find("auth_data not as large as required") != std::string::npos;
222 });
◆ BOOST_AUTO_TEST_CASE() [3/26]
BOOST_AUTO_TEST_CASE |
( |
base64_wonky | | ) |
|
Definition at line 406 of file test_webauthn.cpp.
406 {
407 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
408
410 boost::erase_all(
json,
"=");
411
412 std::vector<uint8_t> auth_data(37);
413 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
414
416 return e.
to_detail_string().find(
"encountered non-base64 character") != std::string::npos;
417 });
Used to generate a useful error report when an exception is thrown.
std::string to_detail_string(log_level ll=log_level::all) const
◆ BOOST_AUTO_TEST_CASE() [4/26]
BOOST_AUTO_TEST_CASE |
( |
challenge_junk | | ) |
|
Definition at line 145 of file test_webauthn.cpp.
145 {
146 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
147 std::string
json =
"{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" +
"blahBLAH"s +
"\"}";
148
149 std::vector<uint8_t> auth_data(37);
150 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
151
153 return e.
to_detail_string().find(
"sha256: size mismatch") != std::string::npos;
154 });
◆ BOOST_AUTO_TEST_CASE() [5/26]
BOOST_AUTO_TEST_CASE |
( |
challenge_non_base64 | | ) |
|
Definition at line 158 of file test_webauthn.cpp.
158 {
159 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
160 std::string
json =
"{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" +
"hello@world$"s +
"\"}";
161
162 std::vector<uint8_t> auth_data(37);
163 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
164
166 return e.
to_detail_string().find(
"encountered non-base64 character") != std::string::npos;
167 });
◆ BOOST_AUTO_TEST_CASE() [6/26]
BOOST_AUTO_TEST_CASE |
( |
challenge_wrong | | ) |
|
Definition at line 171 of file test_webauthn.cpp.
171 {
172 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
174 std::string
json =
"{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\",\"challenge\":\"" +
fc::base64url_encode(other_digest.
data(), other_digest.
data_size()) +
"\"}";
175
176 std::vector<uint8_t> auth_data(37);
177 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
178
179 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
180 return e.to_detail_string().find("Wrong webauthn challenge") != std::string::npos;
181 });
◆ BOOST_AUTO_TEST_CASE() [7/26]
BOOST_AUTO_TEST_CASE |
( |
damage_sig | | ) |
|
Definition at line 290 of file test_webauthn.cpp.
290 {
291 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
293
294 std::vector<uint8_t> auth_data(37);
295 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
296
298 char buff[8192];
301 buff[4]++;
304
305 bool failed_recovery = false;
306 bool failed_compare = false;
308
309 try {
310 recovered_pub = sig.
recover(d,
true);
311 failed_compare = !(wa_pub == recovered_pub);
312 }
314 failed_recovery = e.
to_detail_string().find(
"unable to reconstruct public key from signature") != std::string::npos;
315 }
316
317
318 BOOST_CHECK_EQUAL(failed_recovery || failed_compare, true);
public_key recover(const sha256 &digest, bool check_canonical) const
static const Segment ds(Segment::ds)
void unpack(Stream &s, std::deque< T > &value)
void pack(Stream &s, const std::deque< T > &value)
◆ BOOST_AUTO_TEST_CASE() [8/26]
BOOST_AUTO_TEST_CASE |
( |
damage_sig_idx | | ) |
|
Definition at line 322 of file test_webauthn.cpp.
322 {
323 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
325
326 std::vector<uint8_t> auth_data(37);
327 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
328
330 char buff[8192];
333 buff[0]++;
336
337 bool failed_recovery = false;
338 bool failed_compare = false;
340
341 try {
342 recovered_pub = sig.
recover(d,
true);
343 failed_compare = !(wa_pub == recovered_pub);
344 }
346 failed_recovery = e.
to_detail_string().find(
"unable to reconstruct public key from signature") != std::string::npos;
347 }
348
349
350 BOOST_CHECK_EQUAL(failed_recovery || failed_compare, true);
◆ BOOST_AUTO_TEST_CASE() [9/26]
BOOST_AUTO_TEST_CASE |
( |
different_priv_key | | ) |
|
Definition at line 354 of file test_webauthn.cpp.
354 {
356
357 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
359
360 std::vector<uint8_t> auth_data(37);
361 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
362
363 BOOST_CHECK_NE(wa_pub, make_webauthn_sig(other_priv, auth_data,
json).recover(d,
true));
static private_key generate()
◆ BOOST_AUTO_TEST_CASE() [10/26]
BOOST_AUTO_TEST_CASE |
( |
empty_json | | ) |
|
Definition at line 367 of file test_webauthn.cpp.
367 {
368 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
370
371 std::vector<uint8_t> auth_data(37);
372 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
373
374 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
375 return e.to_detail_string().find("Failed to parse client data JSON") != std::string::npos;
376 });
◆ BOOST_AUTO_TEST_CASE() [11/26]
BOOST_AUTO_TEST_CASE |
( |
empty_origin | | ) |
|
Definition at line 110 of file test_webauthn.cpp.
110 {
111 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
113
114 std::vector<uint8_t> auth_data(37);
115 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
116
117 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
118 return e.to_detail_string().find("webauthn origin must begin with https://") != std::string::npos;
119 });
◆ BOOST_AUTO_TEST_CASE() [12/26]
BOOST_AUTO_TEST_CASE |
( |
empty_port | | ) |
|
Definition at line 134 of file test_webauthn.cpp.
134 {
135 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
137
138 std::vector<uint8_t> auth_data(37);
139 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
140
141 BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [13/26]
BOOST_AUTO_TEST_CASE |
( |
empty_rpid | | ) |
|
Definition at line 380 of file test_webauthn.cpp.
380 {
381 char data[67] = {};
384
385 BOOST_CHECK_EXCEPTION(
fc::raw::unpack(ds,
pubkey), fc::assert_exception, [](
const fc::assert_exception& e) {
386 return e.to_detail_string().find("webauthn pubkey must have non empty rpid") != std::string::npos;
387 });
◆ BOOST_AUTO_TEST_CASE() [14/26]
BOOST_AUTO_TEST_CASE |
( |
good | | ) |
|
Definition at line 48 of file test_webauthn.cpp.
48 {
49 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
51
52 std::vector<uint8_t> auth_data(37);
53
54 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
55
56 BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [15/26]
BOOST_AUTO_TEST_CASE |
( |
good_extrajunk | | ) |
|
Definition at line 265 of file test_webauthn.cpp.
265 {
266 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
267 std::string
json =
"{\"origin\":\"https://fctesting.invalid\",\"cool\":\"beans\",\"obj\":{\"array\":[4, 5, 6]},"
269
270 std::vector<uint8_t> auth_data(37);
271 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
272
273 BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [16/26]
BOOST_AUTO_TEST_CASE |
( |
good_no_trailing_equal | | ) |
|
Definition at line 391 of file test_webauthn.cpp.
391 {
392 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
393
395 boost::erase_all(
json,
"=");
396
397 std::vector<uint8_t> auth_data(37);
398 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
399
400 BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [17/26]
BOOST_AUTO_TEST_CASE |
( |
good_port | | ) |
|
Definition at line 123 of file test_webauthn.cpp.
123 {
124 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
126
127 std::vector<uint8_t> auth_data(37);
128 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
129
130 BOOST_CHECK_EQUAL(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [18/26]
BOOST_AUTO_TEST_CASE |
( |
lacking_scheme | | ) |
|
Definition at line 97 of file test_webauthn.cpp.
97 {
98 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
100
101 std::vector<uint8_t> auth_data(37);
102 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
103
104 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
105 return e.to_detail_string().find("webauthn origin must begin with https://") != std::string::npos;
106 });
◆ BOOST_AUTO_TEST_CASE() [19/26]
BOOST_AUTO_TEST_CASE |
( |
mismatch_origin | | ) |
|
Definition at line 72 of file test_webauthn.cpp.
72 {
73 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_PRESENT,
"fctesting.invalid");
75
76 std::vector<uint8_t> auth_data(37);
78 memcpy(auth_data.data(), mallory_origin_hash.
data(),
sizeof(mallory_origin_hash));
79
80 BOOST_CHECK_NE(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [20/26]
BOOST_AUTO_TEST_CASE |
( |
mismatch_presence | | ) |
|
Definition at line 60 of file test_webauthn.cpp.
60 {
61 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_PRESENT,
"fctesting.invalid");
63
64 std::vector<uint8_t> auth_data(37);
65 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
66 auth_data[32] |= 0x04;
67
68 BOOST_CHECK_NE(wa_pub, make_webauthn_sig(priv, auth_data,
json).recover(d,
true));
◆ BOOST_AUTO_TEST_CASE() [21/26]
BOOST_AUTO_TEST_CASE |
( |
missing_challenge | | ) |
|
Definition at line 252 of file test_webauthn.cpp.
252 {
253 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
254 std::string
json =
"{\"origin\":\"https://fctesting.invalid\",\"type\":\"webauthn.get\"}";
255
256 std::vector<uint8_t> auth_data(37);
257 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
258
260 return e.
to_detail_string().find(
"sha256: size mismatch") != std::string::npos;
261 });
◆ BOOST_AUTO_TEST_CASE() [22/26]
BOOST_AUTO_TEST_CASE |
( |
missing_origin | | ) |
|
Definition at line 226 of file test_webauthn.cpp.
226 {
227 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
229
230 std::vector<uint8_t> auth_data(37);
231 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
232
233 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
234 return e.to_detail_string().find("webauthn origin must begin with https://") != std::string::npos;
235 });
◆ BOOST_AUTO_TEST_CASE() [23/26]
BOOST_AUTO_TEST_CASE |
( |
missing_type | | ) |
|
Definition at line 239 of file test_webauthn.cpp.
239 {
240 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
242
243 std::vector<uint8_t> auth_data(37);
244 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
245
246 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
247 return e.to_detail_string().find("webauthn signature type not an assertion") != std::string::npos;
248 });
◆ BOOST_AUTO_TEST_CASE() [24/26]
BOOST_AUTO_TEST_CASE |
( |
non_https | | ) |
|
Definition at line 84 of file test_webauthn.cpp.
84 {
85 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
87
88 std::vector<uint8_t> auth_data(37);
89 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
90
91 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
92 return e.to_detail_string().find("webauthn origin must begin with https://") != std::string::npos;
93 });
◆ BOOST_AUTO_TEST_CASE() [25/26]
BOOST_AUTO_TEST_CASE |
( |
not_json_object | | ) |
|
Definition at line 277 of file test_webauthn.cpp.
277 {
278 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
279 std::string
json =
"hey man"s;
280
281 std::vector<uint8_t> auth_data(37);
282 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
283
284 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
285 return e.to_detail_string().find("Failed to parse client data JSON") != std::string::npos;
286 });
◆ BOOST_AUTO_TEST_CASE() [26/26]
BOOST_AUTO_TEST_CASE |
( |
wrong_type | | ) |
|
Definition at line 185 of file test_webauthn.cpp.
185 {
186
187 webauthn::public_key wa_pub(pub.serialize(), webauthn::public_key::user_presence_t::USER_PRESENCE_NONE,
"fctesting.invalid");
189
190 std::vector<uint8_t> auth_data(37);
191 memcpy(auth_data.data(), origin_hash.
data(),
sizeof(origin_hash));
192
193 BOOST_CHECK_EXCEPTION(make_webauthn_sig(priv, auth_data,
json).recover(d,
true), fc::assert_exception, [](
const fc::assert_exception& e) {
194 return e.to_detail_string().find("webauthn signature type not an assertion") != std::string::npos;
195 });
◆ FC_LOG_AND_RETHROW()