Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 69 additions & 37 deletions include/libp2p/common/sample_peer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,46 @@

namespace libp2p {
struct SamplePeer {
static constexpr auto Ed25519 = crypto::Key::Type::Ed25519;
static constexpr auto Secp256k1 = crypto::Key::Type::Secp256k1;

static crypto::KeyPair sampleKeypair(size_t index,
crypto::Key::Type key_type) {
crypto::ed25519::PrivateKey private_key;
std::array<uint64_t, sizeof(private_key) / sizeof(uint64_t)> seed64;
static_assert(sizeof(seed64) >= sizeof(private_key));
for (size_t i = 0; i < seed64.size(); ++i) {
seed64.at(i) = i + index;
}
memcpy(private_key.data(), seed64.data(), private_key.size());
crypto::KeyPair keypair{
crypto::PublicKey{{key_type, {}}},
crypto::PrivateKey{{key_type, qtils::ByteVec(private_key)}},
};
switch (key_type) {
case crypto::Key::Type::Ed25519: {
crypto::ed25519::Ed25519ProviderImpl ed25519;
keypair.publicKey.data =
qtils::ByteVec(ed25519.derive(private_key).value());
break;
}
case crypto::Key::Type::Secp256k1: {
crypto::secp256k1::Secp256k1ProviderImpl secp256k1{nullptr};
keypair.publicKey.data =
qtils::ByteVec(secp256k1.derive(private_key).value());
break;
}
default: {
abort();
}
}
return keypair;
}

static uint16_t samplePort(size_t index) {
return 10000 + index;
}

SamplePeer(size_t index,
uint16_t port,
crypto::KeyPair keypair,
Expand All @@ -31,48 +71,26 @@ namespace libp2p {
connect{connect},
connect_info{connect_info} {}

SamplePeer(size_t index, crypto::Key::Type key_type)
SamplePeer(size_t index,
std::string_view ip,
uint16_t port,
crypto::KeyPair keypair)
: SamplePeer{[&] {
uint16_t port = 10000 + index;
crypto::ed25519::PrivateKey private_key;
for (size_t i = 0; i < private_key.size(); ++i) {
private_key.at(i) = i + index;
}
crypto::KeyPair keypair{
crypto::PublicKey{{key_type, {}}},
crypto::PrivateKey{{key_type, qtils::ByteVec(private_key)}},
};
switch (key_type) {
case crypto::Key::Type::Ed25519: {
crypto::ed25519::Ed25519ProviderImpl ed25519;
keypair.publicKey.data =
qtils::ByteVec(ed25519.derive(private_key).value());
break;
}
case crypto::Key::Type::Secp256k1: {
crypto::secp256k1::Secp256k1ProviderImpl secp256k1{nullptr};
keypair.publicKey.data =
qtils::ByteVec(secp256k1.derive(private_key).value());
break;
}
default: {
abort();
}
}
auto peer_id =
peer::IdentityManager{
keypair,
std::make_shared<crypto::marshaller::KeyMarshaller>(
nullptr)}
.getId();
auto listen =
Multiaddress::create(
std::format("/ip4/127.0.0.1/udp/{}/quic-v1", port))
.value();
auto connect =
Multiaddress::create(
std::format("{}/p2p/{}", listen, peer_id.toBase58()))
.value();
auto listen = Multiaddress::create(
std::format("/ip4/0.0.0.0/udp/{}/quic-v1", port))
.value();
auto connect = Multiaddress::create(
std::format("/ip4/{}/udp/{}/quic-v1/p2p/{}",
ip,
port,
peer_id.toBase58()))
.value();
return SamplePeer{
index,
port,
Expand All @@ -84,12 +102,26 @@ namespace libp2p {
};
}()} {}

SamplePeer(size_t index,
std::string_view ip,
uint16_t port,
crypto::Key::Type key_type)
: SamplePeer{index, ip, port, sampleKeypair(index, key_type)} {}

SamplePeer(size_t index, crypto::Key::Type key_type)
: SamplePeer{
index,
"127.0.0.1",
samplePort(index),
key_type,
} {}

static SamplePeer makeEd25519(size_t index) {
return SamplePeer{index, crypto::Key::Type::Ed25519};
return SamplePeer{index, Ed25519};
}

static SamplePeer makeSecp256k1(size_t index) {
return SamplePeer{index, crypto::Key::Type::Secp256k1};
return SamplePeer{index, Secp256k1};
}

size_t index;
Expand Down
6 changes: 6 additions & 0 deletions include/libp2p/crypto/secp256k1_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace libp2p::crypto::secp256k1 {
*/
virtual outcome::result<Signature> sign(BytesIn message,
const PrivateKey &key) const = 0;
virtual outcome::result<SignatureCompact> signCompact(
const Prehashed &prehashed, const PrivateKey &key) const = 0;

/**
* @brief Verify signature for a message
Expand All @@ -49,6 +51,10 @@ namespace libp2p::crypto::secp256k1 {
virtual outcome::result<bool> verify(BytesIn message,
const Signature &signature,
const PublicKey &key) const = 0;
virtual outcome::result<bool> verifyCompact(
const Prehashed &prehashed,
const SignatureCompact &signature,
const PublicKey &key) const = 0;

virtual ~Secp256k1Provider() = default;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,23 @@ namespace libp2p::crypto::secp256k1 {

outcome::result<Signature> sign(BytesIn message,
const PrivateKey &key) const override;
outcome::result<SignatureCompact> signCompact(
const Prehashed &prehashed, const PrivateKey &key) const override;

outcome::result<bool> verify(BytesIn message,
const Signature &signature,
const PublicKey &key) const override;
outcome::result<bool> verifyCompact(const Prehashed &prehashed,
const SignatureCompact &signature,
const PublicKey &key) const override;

private:
outcome::result<secp256k1_ecdsa_signature> signRaw(
const Prehashed &prehashed, const PrivateKey &key) const;
outcome::result<bool> verifyRaw(const Prehashed &prehashed,
const secp256k1_ecdsa_signature &ffi_sig,
const PublicKey &key) const;

std::shared_ptr<random::CSPRNG> random_;
std::unique_ptr<secp256k1_context, void (*)(secp256k1_context *)> ctx_;
};
Expand Down
4 changes: 4 additions & 0 deletions include/libp2p/crypto/secp256k1_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ namespace libp2p::crypto::secp256k1 {

static const size_t kPrivateKeyLength = 32;
static const size_t kPublicKeyLength = 33;
static const size_t kSignatureCompactLength = 64;
static const size_t kPrehashedLength = 32;
/**
* @brief Common types
*/
using PrivateKey = std::array<uint8_t, kPrivateKeyLength>;
using PublicKey = std::array<uint8_t, kPublicKeyLength>;
using Signature = std::vector<uint8_t>;
using SignatureCompact = std::array<uint8_t, kSignatureCompactLength>;
using Prehashed = std::array<uint8_t, kPrehashedLength>;

/**
* @struct Key pair
Expand Down
26 changes: 26 additions & 0 deletions include/libp2p/crypto/sha/keccak.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// https://github.com/nayuki/Bitcoin-Cryptography-Library/blob/master/cpp/Keccak256.hpp
// Not using https://vcpkg.io/en/package/keccak-tiny from vcpkg because it only
// exports sha3, not keccak

#pragma once

#include <qtils/byte_arr.hpp>

namespace libp2p {
class Keccak {
public:
using Hash32 = qtils::ByteArr<32>;

void update(uint8_t byte);
Keccak &update(qtils::BytesIn input);
Hash32 finalize();
Hash32 hash() const;
static Hash32 hash(qtils::BytesIn input);

private:
void absorb();

uint64_t state[5][5] = {};
size_t blockOff = 0;
};
} // namespace libp2p
68 changes: 51 additions & 17 deletions src/crypto/secp256k1_provider/secp256k1_provider_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,7 @@ namespace libp2p::crypto::secp256k1 {

outcome::result<Signature> Secp256k1ProviderImpl::sign(
BytesIn message, const PrivateKey &key) const {
OUTCOME_TRY(digest, sha256(message));
secp256k1_ecdsa_signature ffi_sig;
if (secp256k1_ecdsa_sign(ctx_.get(),
&ffi_sig,
digest.data(),
key.data(),
secp256k1_nonce_function_rfc6979,
nullptr)
== 0) {
return CryptoProviderError::SIGNATURE_GENERATION_FAILED;
}
OUTCOME_TRY(ffi_sig, signRaw(sha256(message).value(), key));
uint8_t empty = 0;
size_t size = 0;
secp256k1_ecdsa_signature_serialize_der(
Expand All @@ -74,21 +64,65 @@ namespace libp2p::crypto::secp256k1 {
return signature;
}

outcome::result<SignatureCompact> Secp256k1ProviderImpl::signCompact(
const Prehashed &prehashed, const PrivateKey &key) const {
OUTCOME_TRY(ffi_sig, signRaw(prehashed, key));
SignatureCompact signature;
secp256k1_ecdsa_signature_serialize_compact(
ctx_.get(), signature.data(), &ffi_sig);
return signature;
}

outcome::result<bool> Secp256k1ProviderImpl::verify(
BytesIn message, const Signature &signature, const PublicKey &key) const {
OUTCOME_TRY(digest, sha256(message));
secp256k1_pubkey ffi_pub;
if (secp256k1_ec_pubkey_parse(ctx_.get(), &ffi_pub, key.data(), key.size())
secp256k1_ecdsa_signature ffi_sig;
if (secp256k1_ecdsa_signature_parse_der(
ctx_.get(), &ffi_sig, signature.data(), signature.size())
== 0) {
return CryptoProviderError::SIGNATURE_VERIFICATION_FAILED;
}
return verifyRaw(sha256(message).value(), ffi_sig, key);
}

outcome::result<bool> Secp256k1ProviderImpl::verifyCompact(
const Prehashed &prehashed,
const SignatureCompact &signature,
const PublicKey &key) const {
secp256k1_ecdsa_signature ffi_sig;
if (secp256k1_ecdsa_signature_parse_der(
ctx_.get(), &ffi_sig, signature.data(), signature.size())
if (secp256k1_ecdsa_signature_parse_compact(
ctx_.get(), &ffi_sig, signature.data())
== 0) {
return CryptoProviderError::SIGNATURE_VERIFICATION_FAILED;
}
return verifyRaw(prehashed, ffi_sig, key);
}

outcome::result<secp256k1_ecdsa_signature> Secp256k1ProviderImpl::signRaw(
const Prehashed &prehashed, const PrivateKey &key) const {
secp256k1_ecdsa_signature ffi_sig;
if (secp256k1_ecdsa_sign(ctx_.get(),
&ffi_sig,
prehashed.data(),
key.data(),
secp256k1_nonce_function_rfc6979,
nullptr)
== 0) {
return CryptoProviderError::SIGNATURE_GENERATION_FAILED;
}
return ffi_sig;
}

outcome::result<bool> Secp256k1ProviderImpl::verifyRaw(
const Prehashed &prehashed,
const secp256k1_ecdsa_signature &ffi_sig,
const PublicKey &key) const {
secp256k1_pubkey ffi_pub;
if (secp256k1_ec_pubkey_parse(ctx_.get(), &ffi_pub, key.data(), key.size())
== 0) {
return CryptoProviderError::SIGNATURE_VERIFICATION_FAILED;
}
return secp256k1_ecdsa_verify(ctx_.get(), &ffi_sig, digest.data(), &ffi_pub)
return secp256k1_ecdsa_verify(
ctx_.get(), &ffi_sig, prehashed.data(), &ffi_pub)
== 1;
}
} // namespace libp2p::crypto::secp256k1
1 change: 1 addition & 0 deletions src/crypto/sha/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#

libp2p_add_library(p2p_sha
keccak.cpp
sha1.cpp
sha256.cpp
sha512.cpp
Expand Down
Loading
Loading