add basic discord support

This commit is contained in:
2024-11-09 01:58:06 +03:00
parent c3e7a9c92d
commit 8965b7ee90
869 changed files with 191278 additions and 7 deletions

View File

@@ -0,0 +1,20 @@
#pragma once
#include <bytes/bytes.h>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
std::string
to_base64(const bytes& data);
std::string
to_base64url(const bytes& data);
bytes
from_base64(const std::string& enc);
bytes
from_base64url(const std::string& enc);
} // namespace mlspp::hpke

View File

@@ -0,0 +1,75 @@
#pragma once
#include <memory>
#include <optional>
#include <bytes/bytes.h>
#include <chrono>
#include <hpke/signature.h>
#include <map>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
struct Certificate
{
private:
struct ParsedCertificate;
std::unique_ptr<ParsedCertificate> parsed_cert;
public:
struct NameType
{
static const int organization;
static const int common_name;
static const int organizational_unit;
static const int country;
static const int serial_number;
static const int state_or_province_name;
};
using ParsedName = std::map<int, std::string>;
// Certificate Expiration Status
enum struct ExpirationStatus
{
inactive, // now < notBefore
active, // notBefore < now < notAfter
expired, // notAfter < now
};
explicit Certificate(const bytes& der);
explicit Certificate(std::unique_ptr<ParsedCertificate>&& parsed_cert_in);
Certificate() = delete;
Certificate(const Certificate& other);
~Certificate();
static std::vector<Certificate> parse_pem(const bytes& pem);
bool valid_from(const Certificate& parent) const;
// Accessors for parsed certificate elements
uint64_t issuer_hash() const;
uint64_t subject_hash() const;
ParsedName issuer() const;
ParsedName subject() const;
bool is_ca() const;
ExpirationStatus expiration_status() const;
std::optional<bytes> subject_key_id() const;
std::optional<bytes> authority_key_id() const;
std::vector<std::string> email_addresses() const;
std::vector<std::string> dns_names() const;
bytes hash() const;
std::chrono::system_clock::time_point not_before() const;
std::chrono::system_clock::time_point not_after() const;
Signature::ID public_key_algorithm() const;
Signature::ID signature_algorithm() const;
const std::unique_ptr<Signature::PublicKey> public_key;
const bytes raw;
};
bool
operator==(const Certificate& lhs, const Certificate& rhs);
} // namespace mlspp::hpke

View File

@@ -0,0 +1,37 @@
#pragma once
#include <memory>
#include <bytes/bytes.h>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
struct Digest
{
enum struct ID
{
SHA256,
SHA384,
SHA512,
};
template<ID id>
static const Digest& get();
const ID id;
bytes hash(const bytes& data) const;
bytes hmac(const bytes& key, const bytes& data) const;
const size_t hash_size;
private:
explicit Digest(ID id);
bytes hmac_for_hkdf_extract(const bytes& key, const bytes& data) const;
friend struct HKDF;
};
} // namespace mlspp::hpke

View File

@@ -0,0 +1,253 @@
#pragma once
#include <memory>
#include <optional>
#include <bytes/bytes.h>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
struct KEM
{
enum struct ID : uint16_t
{
DHKEM_P256_SHA256 = 0x0010,
DHKEM_P384_SHA384 = 0x0011,
DHKEM_P521_SHA512 = 0x0012,
DHKEM_X25519_SHA256 = 0x0020,
#if !defined(WITH_BORINGSSL)
DHKEM_X448_SHA512 = 0x0021,
#endif
};
template<KEM::ID>
static const KEM& get();
virtual ~KEM() = default;
struct PublicKey
{
virtual ~PublicKey() = default;
};
struct PrivateKey
{
virtual ~PrivateKey() = default;
virtual std::unique_ptr<PublicKey> public_key() const = 0;
};
const ID id;
const size_t secret_size;
const size_t enc_size;
const size_t pk_size;
const size_t sk_size;
virtual std::unique_ptr<PrivateKey> generate_key_pair() const = 0;
virtual std::unique_ptr<PrivateKey> derive_key_pair(
const bytes& ikm) const = 0;
virtual bytes serialize(const PublicKey& pk) const = 0;
virtual std::unique_ptr<PublicKey> deserialize(const bytes& enc) const = 0;
virtual bytes serialize_private(const PrivateKey& sk) const;
virtual std::unique_ptr<PrivateKey> deserialize_private(
const bytes& skm) const;
// (shared_secret, enc)
virtual std::pair<bytes, bytes> encap(const PublicKey& pkR) const = 0;
virtual bytes decap(const bytes& enc, const PrivateKey& skR) const = 0;
// (shared_secret, enc)
virtual std::pair<bytes, bytes> auth_encap(const PublicKey& pkR,
const PrivateKey& skS) const;
virtual bytes auth_decap(const bytes& enc,
const PublicKey& pkS,
const PrivateKey& skR) const;
protected:
KEM(ID id_in,
size_t secret_size_in,
size_t enc_size_in,
size_t pk_size_in,
size_t sk_size_in);
};
struct KDF
{
enum struct ID : uint16_t
{
HKDF_SHA256 = 0x0001,
HKDF_SHA384 = 0x0002,
HKDF_SHA512 = 0x0003,
};
template<KDF::ID id>
static const KDF& get();
virtual ~KDF() = default;
const ID id;
const size_t hash_size;
virtual bytes extract(const bytes& salt, const bytes& ikm) const = 0;
virtual bytes expand(const bytes& prk,
const bytes& info,
size_t size) const = 0;
bytes labeled_extract(const bytes& suite_id,
const bytes& salt,
const bytes& label,
const bytes& ikm) const;
bytes labeled_expand(const bytes& suite_id,
const bytes& prk,
const bytes& label,
const bytes& info,
size_t size) const;
protected:
KDF(ID id_in, size_t hash_size_in);
};
struct AEAD
{
enum struct ID : uint16_t
{
AES_128_GCM = 0x0001,
AES_256_GCM = 0x0002,
CHACHA20_POLY1305 = 0x0003,
// Reserved identifier for pseudo-AEAD on contexts that only allow export
export_only = 0xffff,
};
template<AEAD::ID id>
static const AEAD& get();
virtual ~AEAD() = default;
const ID id;
const size_t key_size;
const size_t nonce_size;
virtual bytes seal(const bytes& key,
const bytes& nonce,
const bytes& aad,
const bytes& pt) const = 0;
virtual std::optional<bytes> open(const bytes& key,
const bytes& nonce,
const bytes& aad,
const bytes& ct) const = 0;
protected:
AEAD(ID id_in, size_t key_size_in, size_t nonce_size_in);
};
struct Context
{
bytes do_export(const bytes& exporter_context, size_t size) const;
protected:
bytes suite;
bytes key;
bytes nonce;
bytes exporter_secret;
const KDF& kdf;
const AEAD& aead;
bytes current_nonce() const;
void increment_seq();
private:
uint64_t seq;
Context(bytes suite_in,
bytes key_in,
bytes nonce_in,
bytes exporter_secret_in,
const KDF& kdf_in,
const AEAD& aead_in);
friend struct HPKE;
friend struct HPKETest;
friend bool operator==(const Context& lhs, const Context& rhs);
};
struct SenderContext : public Context
{
SenderContext(Context&& c);
bytes seal(const bytes& aad, const bytes& pt);
};
struct ReceiverContext : public Context
{
ReceiverContext(Context&& c);
std::optional<bytes> open(const bytes& aad, const bytes& ct);
};
struct HPKE
{
enum struct Mode : uint8_t
{
base = 0,
psk = 1,
auth = 2,
auth_psk = 3,
};
HPKE(KEM::ID kem_id, KDF::ID kdf_id, AEAD::ID aead_id);
using SenderInfo = std::pair<bytes, SenderContext>;
SenderInfo setup_base_s(const KEM::PublicKey& pkR, const bytes& info) const;
ReceiverContext setup_base_r(const bytes& enc,
const KEM::PrivateKey& skR,
const bytes& info) const;
SenderInfo setup_psk_s(const KEM::PublicKey& pkR,
const bytes& info,
const bytes& psk,
const bytes& psk_id) const;
ReceiverContext setup_psk_r(const bytes& enc,
const KEM::PrivateKey& skR,
const bytes& info,
const bytes& psk,
const bytes& psk_id) const;
SenderInfo setup_auth_s(const KEM::PublicKey& pkR,
const bytes& info,
const KEM::PrivateKey& skS) const;
ReceiverContext setup_auth_r(const bytes& enc,
const KEM::PrivateKey& skR,
const bytes& info,
const KEM::PublicKey& pkS) const;
SenderInfo setup_auth_psk_s(const KEM::PublicKey& pkR,
const bytes& info,
const bytes& psk,
const bytes& psk_id,
const KEM::PrivateKey& skS) const;
ReceiverContext setup_auth_psk_r(const bytes& enc,
const KEM::PrivateKey& skR,
const bytes& info,
const bytes& psk,
const bytes& psk_id,
const KEM::PublicKey& pkS) const;
bytes suite;
const KEM& kem;
const KDF& kdf;
const AEAD& aead;
private:
static bool verify_psk_inputs(Mode mode,
const bytes& psk,
const bytes& psk_id);
Context key_schedule(Mode mode,
const bytes& shared_secret,
const bytes& info,
const bytes& psk,
const bytes& psk_id) const;
};
} // namespace mlspp::hpke

View File

@@ -0,0 +1,11 @@
#pragma once
#include <bytes/bytes.h>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
bytes
random_bytes(size_t size);
} // namespace mlspp::hpke

View File

@@ -0,0 +1,89 @@
#pragma once
#include <memory>
#include <bytes/bytes.h>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
struct Signature
{
enum struct ID
{
P256_SHA256,
P384_SHA384,
P521_SHA512,
Ed25519,
#if !defined(WITH_BORINGSSL)
Ed448,
#endif
RSA_SHA256,
RSA_SHA384,
RSA_SHA512,
};
template<Signature::ID id>
static const Signature& get();
virtual ~Signature() = default;
struct PublicKey
{
virtual ~PublicKey() = default;
};
struct PrivateKey
{
virtual ~PrivateKey() = default;
virtual std::unique_ptr<PublicKey> public_key() const = 0;
};
const ID id;
virtual std::unique_ptr<PrivateKey> generate_key_pair() const = 0;
virtual std::unique_ptr<PrivateKey> derive_key_pair(
const bytes& ikm) const = 0;
virtual bytes serialize(const PublicKey& pk) const = 0;
virtual std::unique_ptr<PublicKey> deserialize(const bytes& enc) const = 0;
virtual bytes serialize_private(const PrivateKey& sk) const = 0;
virtual std::unique_ptr<PrivateKey> deserialize_private(
const bytes& skm) const = 0;
struct PrivateJWK
{
const Signature& sig;
std::optional<std::string> key_id;
std::unique_ptr<PrivateKey> key;
};
static PrivateJWK parse_jwk_private(const std::string& jwk_json);
struct PublicJWK
{
const Signature& sig;
std::optional<std::string> key_id;
std::unique_ptr<PublicKey> key;
};
static PublicJWK parse_jwk(const std::string& jwk_json);
virtual std::unique_ptr<PrivateKey> import_jwk_private(
const std::string& jwk_json) const = 0;
virtual std::unique_ptr<PublicKey> import_jwk(
const std::string& jwk_json) const = 0;
virtual std::string export_jwk_private(const PrivateKey& env) const = 0;
virtual std::string export_jwk(const PublicKey& env) const = 0;
virtual bytes sign(const bytes& data, const PrivateKey& sk) const = 0;
virtual bool verify(const bytes& data,
const bytes& sig,
const PublicKey& pk) const = 0;
static std::unique_ptr<PrivateKey> generate_rsa(size_t bits);
protected:
Signature(ID id_in);
};
} // namespace mlspp::hpke

View File

@@ -0,0 +1,82 @@
#pragma once
#include <memory>
#include <optional>
#include <bytes/bytes.h>
#include <chrono>
#include <hpke/signature.h>
#include <map>
using namespace mlspp::bytes_ns;
namespace mlspp::hpke {
struct UserInfoClaimsAddress
{
std::optional<std::string> formatted;
std::optional<std::string> street_address;
std::optional<std::string> locality;
std::optional<std::string> region;
std::optional<std::string> postal_code;
std::optional<std::string> country;
};
struct UserInfoClaims
{
std::optional<std::string> sub;
std::optional<std::string> name;
std::optional<std::string> given_name;
std::optional<std::string> family_name;
std::optional<std::string> middle_name;
std::optional<std::string> nickname;
std::optional<std::string> preferred_username;
std::optional<std::string> profile;
std::optional<std::string> picture;
std::optional<std::string> website;
std::optional<std::string> email;
std::optional<bool> email_verified;
std::optional<std::string> gender;
std::optional<std::string> birthdate;
std::optional<std::string> zoneinfo;
std::optional<std::string> locale;
std::optional<std::string> phone_number;
std::optional<bool> phone_number_verified;
std::optional<UserInfoClaimsAddress> address;
std::optional<uint64_t> updated_at;
static UserInfoClaims from_json(const std::string& cred_subject);
};
struct UserInfoVC
{
private:
struct ParsedCredential;
std::shared_ptr<ParsedCredential> parsed_cred;
public:
explicit UserInfoVC(std::string jwt);
UserInfoVC() = default;
UserInfoVC(const UserInfoVC& other) = default;
~UserInfoVC() = default;
UserInfoVC& operator=(const UserInfoVC& other) = default;
UserInfoVC& operator=(UserInfoVC&& other) = default;
const Signature& signature_algorithm() const;
std::string issuer() const;
std::optional<std::string> key_id() const;
std::chrono::system_clock::time_point not_before() const;
std::chrono::system_clock::time_point not_after() const;
const std::string& raw_credential() const;
const UserInfoClaims& subject() const;
const Signature::PublicJWK& public_key() const;
bool valid_from(const Signature::PublicKey& issuer_key) const;
std::string raw;
};
bool
operator==(const UserInfoVC& lhs, const UserInfoVC& rhs);
} // namespace mlspp::hpke