#ifndef DID_NOSTR_HPP
#define DID_NOSTR_HPP
#include <string>
#include <memory>
#include <stdexcept>
#include <algorithm>
namespace http_privacy {
namespace did_nostr {
class NostrPublicKey {
private:
std::string hex_;
public:
explicit NostrPublicKey(const std::string& hex) : hex_(hex) {
if (!is_valid_hex(hex)) {
throw std::invalid_argument("Invalid Nostr public key hex string. Must be 64 hex characters.");
}
}
const std::string& as_hex() const;
std::string to_string() const {
if (hex_.length() <= 16) {
return hex_;
}
return hex_.substr(0, 8) + "..." + hex_.substr(hex_.length() - 8);
}
static bool is_valid_hex(const std::string& hex) {
if (hex.length() != 64) return false;
return std::all_of(hex.begin(), hex.end(), [](char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
});
}
};
class DidNostr {
private:
NostrPublicKey pubkey_;
public:
explicit DidNostr(const NostrPublicKey& pubkey) : pubkey_(pubkey) {}
static DidNostr from_str(const std::string& did_str) {
if (!did_str.starts_with("did:nostr:")) {
throw std::invalid_argument("Invalid DID-NOSTR format. Must start with 'did:nostr:'.");
}
std::string hex = did_str.substr(10); return DidNostr(NostrPublicKey(hex));
}
const NostrPublicKey& pubkey() const { return pubkey_; }
std::string to_string() const {
return "did:nostr:" + pubkey_.as_hex();
}
};
class NostrSignature {
private:
std::string hex_;
public:
explicit NostrSignature(const std::string& hex) : hex_(hex) {
if (!is_valid_hex(hex)) {
throw std::invalid_argument("Invalid Nostr signature hex string. Must be 128 hex characters.");
}
}
const std::string& as_hex() const { return hex_; }
std::string to_string() const {
if (hex_.length() <= 16) {
return hex_;
}
return hex_.substr(0, 8) + "..." + hex_.substr(hex_.length() - 8);
}
static bool is_valid_hex(const std::string& hex) {
if (hex.length() != 128) return false;
return std::all_of(hex.begin(), hex.end(), [](char c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
});
}
};
struct VerificationResult {
bool valid;
std::string did; std::string error;
bool is_valid() const { return valid; }
};
class NostrVerifier {
public:
static VerificationResult verify(
const NostrPublicKey& pubkey,
const std::string& message,
const NostrSignature& signature
) {
bool valid = !message.empty() && signature.as_hex().length() == 128;
std::string error_msg = valid ? "" : "Simulated verification failed.";
return {valid, valid ? pubkey.as_hex() : "", error_msg};
}
};
class RequestCanonicalizer {
public:
static std::string canonicalize(
const std::string& method,
const std::string& path,
const std::vector<std::pair<std::string, std::string>>& headers,
const std::string& body
) {
std::string canonical_form;
canonical_form += method + "\n";
canonical_form += path + "\n";
std::vector<std::pair<std::string, std::string>> sorted_headers = headers;
std::sort(sorted_headers.begin(), sorted_headers.end(),
[](const auto& a, const auto& b) {
return a.first < b.first;
});
for (const auto& header : sorted_headers) {
if (header.first != "Authorization" && header.first != "authorization") {
canonical_form += header.first + ":" + header.second + "\n";
}
}
canonical_form += "\n"; canonical_form += body;
return canonical_form;
}
};
} }
#endif