summaryrefslogtreecommitdiff
path: root/src/pubkey.cpp
blob: 3247ce2fcbf2893aeb5ce0a93f3b876999d8e7ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "pubkey.h"

#include <stdexcept>

using std::unique_ptr;
using std::runtime_error;
using std::string;

using namespace erebos;

optional<PublicKey> PublicKey::load(const Ref & ref)
{
	auto rec = ref->asRecord();
	if (!rec)
		return nullopt;

	if (auto ktype = rec->item("type").asText())
		if (ktype.value() != "ed25519")
			throw runtime_error("unsupported key type " + ktype.value());

	if (auto pubkey = rec->item("pubkey").asBinary())
		return PublicKey(EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr,
					pubkey.value().data(), pubkey.value().size()));

	return nullopt;
}

optional<Signature> Signature::load(const Ref & ref)
{
	auto rec = ref->asRecord();
	if (!rec)
		return nullopt;

	auto key = rec->item("key").as<PublicKey>();
	auto sig = rec->item("sig").asBinary();

	if (!key || !sig)
		return nullopt;

	return Signature {
		.key = key.value(),
		.sig = sig.value(),
	};
}

bool Signature::verify(const Ref & ref) const
{
	unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>
		mdctx(EVP_MD_CTX_create(), &EVP_MD_CTX_free);
	if (!mdctx)
		throw runtime_error("failed to create EVP_MD_CTX");

	if (EVP_DigestVerifyInit(mdctx.get(), nullptr, EVP_md_null(),
				nullptr, key->key.get()) != 1)
		throw runtime_error("failed to initialize EVP_MD_CTX");

	return EVP_DigestVerify(mdctx.get(), sig.data(), sig.size(),
			ref.digest().arr().data(), Digest::size) == 1;
}