Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
fc::crypto::webauthn::public_key Class Reference

#include <elliptic_webauthn.hpp>

Public Types

enum class  user_presence_t : uint8_t { USER_PRESENCE_NONE , USER_PRESENCE_PRESENT , USER_PRESENCE_VERIFIED }
 
using public_key_data_type = fc::array<char, 33>
 
using data_type = public_key
 

Public Member Functions

public_key serialize () const
 
bool valid () const
 
 public_key ()
 
 public_key (const public_key_data_type &p, const user_presence_t &t, const std::string &s)
 
 public_key (const signature &c, const fc::sha256 &digest, bool check_canonical=true)
 
bool operator== (const public_key &o) const
 
bool operator< (const public_key &o) const
 

Friends

template<typename Stream >
Streamoperator<< (Stream &ds, const public_key &k)
 
template<typename Stream >
Streamoperator>> (Stream &ds, public_key &k)
 

Detailed Description

Definition at line 15 of file elliptic_webauthn.hpp.

Member Typedef Documentation

◆ data_type

◆ public_key_data_type

Member Enumeration Documentation

◆ user_presence_t

Enumerator
USER_PRESENCE_NONE 
USER_PRESENCE_PRESENT 
USER_PRESENCE_VERIFIED 

Definition at line 23 of file elliptic_webauthn.hpp.

Constructor & Destructor Documentation

◆ public_key() [1/3]

fc::crypto::webauthn::public_key::public_key ( )
inline

Definition at line 31 of file elliptic_webauthn.hpp.

31{}

◆ public_key() [2/3]

fc::crypto::webauthn::public_key::public_key ( const public_key_data_type & p,
const user_presence_t & t,
const std::string & s )
inline

Definition at line 32 of file elliptic_webauthn.hpp.

32 :
33 public_key_data(p), user_verification_type(t), rpid(s) {
34 post_init();
35 }
const mie::Vuint & p
Definition bn.cpp:27
char * s

◆ public_key() [3/3]

fc::crypto::webauthn::public_key::public_key ( const signature & c,
const fc::sha256 & digest,
bool check_canonical = true )

Definition at line 189 of file elliptic_webauthn.cpp.

189 {
190 detail::webauthn_json_handler handler;
191 detail::rapidjson::Reader reader;
192 detail::rapidjson::StringStream ss(c.client_json.c_str());
193 FC_ASSERT(reader.Parse<detail::rapidjson::kParseIterativeFlag>(ss, handler), "Failed to parse client data JSON");
194
195 FC_ASSERT(handler.found_type == "webauthn.get", "webauthn signature type not an assertion");
196
197 std::string challenge_bytes = fc::base64url_decode(handler.found_challenge);
198 FC_ASSERT(fc::sha256(challenge_bytes.data(), challenge_bytes.size()) == digest, "Wrong webauthn challenge");
199
200 char required_origin_scheme[] = "https://";
201 size_t https_len = strlen(required_origin_scheme);
202 FC_ASSERT(handler.found_origin.compare(0, https_len, required_origin_scheme) == 0, "webauthn origin must begin with https://");
203 rpid = handler.found_origin.substr(https_len, handler.found_origin.rfind(':')-https_len);
204
205 constexpr static size_t min_auth_data_size = 37;
206 FC_ASSERT(c.auth_data.size() >= min_auth_data_size, "auth_data not as large as required");
207 if(c.auth_data[32] & 0x01)
208 user_verification_type = user_presence_t::USER_PRESENCE_PRESENT;
209 if(c.auth_data[32] & 0x04)
210 user_verification_type = user_presence_t::USER_PRESENCE_VERIFIED;
211
212 static_assert(min_auth_data_size >= sizeof(fc::sha256), "auth_data min size not enough to store a sha256");
213 FC_ASSERT(memcmp(c.auth_data.data(), fc::sha256::hash(rpid).data(), sizeof(fc::sha256)) == 0, "webauthn rpid hash doesn't match origin");
214
215 //the signature (and thus public key we need to return) will be over
216 // sha256(auth_data || client_data_hash)
217 fc::sha256 client_data_hash = fc::sha256::hash(c.client_json);
219 e.write((char*)c.auth_data.data(), c.auth_data.size());
220 e.write(client_data_hash.data(), client_data_hash.data_size());
221 fc::sha256 signed_digest = e.result();
222
223 //quite a bit of this copied from elliptic_r1, can probably commonize
224 int nV = c.compact_signature.data[0];
225 if (nV<31 || nV>=35)
226 FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
227 ecdsa_sig sig = ECDSA_SIG_new();
228 BIGNUM *r = BN_new(), *s = BN_new();
229 BN_bin2bn(&c.compact_signature.data[1],32,r);
230 BN_bin2bn(&c.compact_signature.data[33],32,s);
231 ECDSA_SIG_set0(sig, r, s);
232
233 fc::ec_key key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
234 nV -= 4;
235
236 if (r1::ECDSA_SIG_recover_key_GFp(key, sig, (uint8_t*)signed_digest.data(), signed_digest.data_size(), nV - 27, 0) == 1) {
237 const EC_POINT* point = EC_KEY_get0_public_key(key);
238 const EC_GROUP* group = EC_KEY_get0_group(key);
239 size_t sz = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, (uint8_t*)public_key_data.data, public_key_data.size(), NULL);
240 if(sz == public_key_data.size())
241 return;
242 }
243 FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
244}
const mie::Vuint & r
Definition bn.cpp:28
size_t size() const
Definition array.hpp:35
T data[N]
Definition array.hpp:37
void write(const char *d, uint32_t dlen)
Definition sha256.cpp:59
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
const char * data() const
Definition sha256.cpp:31
size_t data_size() const
Definition sha256.hpp:23
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
bignum_st BIGNUM
Definition bigint.hpp:7
static const Segment ss(Segment::ss)
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
fc::sha256 digest(const T &value)
Definition digest.hpp:9
std::string base64url_decode(const std::string &encoded_string)
Definition base64.cpp:156
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
Here is the call graph for this function:

Member Function Documentation

◆ operator<()

bool fc::crypto::webauthn::public_key::operator< ( const public_key & o) const
inline

Definition at line 43 of file elliptic_webauthn.hpp.

43 {
44 return std::tie(public_key_data, user_verification_type, rpid) < std::tie(o.public_key_data, o.user_verification_type, o.rpid);
45 }

◆ operator==()

bool fc::crypto::webauthn::public_key::operator== ( const public_key & o) const
inline

Definition at line 38 of file elliptic_webauthn.hpp.

38 {
39 return public_key_data == o.public_key_data &&
40 user_verification_type == o.user_verification_type &&
41 rpid == o.rpid;
42 }

◆ serialize()

public_key fc::crypto::webauthn::public_key::serialize ( ) const
inline

Definition at line 21 of file elliptic_webauthn.hpp.

21{ return *this; }

◆ valid()

bool fc::crypto::webauthn::public_key::valid ( ) const
inline

Definition at line 29 of file elliptic_webauthn.hpp.

29{ return rpid.size(); }

Friends And Related Symbol Documentation

◆ operator<<

template<typename Stream >
Stream & operator<< ( Stream & ds,
const public_key & k )
friend

Definition at line 48 of file elliptic_webauthn.hpp.

48 {
49 fc::raw::pack(ds, k.public_key_data);
50 fc::raw::pack(ds, static_cast<uint8_t>(k.user_verification_type));
51 fc::raw::pack(ds, k.rpid);
52 return ds;
53 }
static const Segment ds(Segment::ds)
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531

◆ operator>>

template<typename Stream >
Stream & operator>> ( Stream & ds,
public_key & k )
friend

Definition at line 56 of file elliptic_webauthn.hpp.

56 {
57 fc::raw::unpack(ds, k.public_key_data);
58 uint8_t t;
59 fc::raw::unpack(ds, t);
60 k.user_verification_type = static_cast<user_presence_t>(t);
61 fc::raw::unpack(ds, k.rpid);
62 k.post_init();
63 return ds;
64 }
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540

The documentation for this class was generated from the following files: