Skip to content
This repository has been archived by the owner on Jun 12, 2018. It is now read-only.

Commit

Permalink
MUL-1212: GOLOS signing with private key
Browse files Browse the repository at this point in the history
   * add implementatino golos private_key::sign
   * add test to verify golos signature
  • Loading branch information
PashaKlybik committed Apr 6, 2018
1 parent 33a70ec commit 6ab6969
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 4 deletions.
55 changes: 52 additions & 3 deletions multy_core/src/golos/golos_account.cpp
Expand Up @@ -19,10 +19,19 @@
#include "wally_core.h"
#include "wally_crypto.h"

extern "C" {
#include "libwally-core/src/internal.h"
}
#include "libwally-core/src/secp256k1/include/secp256k1.h"

#include <cassert>

#include <string.h>

#define GOLOS_RECOVERY_PARAM_COMPRESSED 4
#define GOLOS_RECOVERY_PARAM_COMPACT 27
#define GOLOS_SIGNATURE_SIZE 65

namespace
{
using namespace multy_core::internal;
Expand All @@ -43,6 +52,26 @@ uint32_t get_chain_index(BlockchainType blockchain_type)
return blockchain_type.blockchain;
}

// Check that signature is in canonical format
// For details please see: bitshares/bitshares1-core#1129
bool is_canonical_signature(const std::array<unsigned char, GOLOS_SIGNATURE_SIZE>& c )
{
return !(c[1] & 0x80)
&& !(c[1] == 0 && !(c[2] & 0x80))
&& !(c[33] & 0x80)
&& !(c[33] == 0 && !(c[34] & 0x80));
}

// This extended nonce function is based on Golos implementation
static int extended_nonce_function( unsigned char *nonce32, const unsigned char *msg32,
const unsigned char *key32, const unsigned char* /*algo16*/,
void *data, unsigned int /*attempt*/)
{
unsigned int* extra = (unsigned int*) data;
(*extra)++;
return secp256k1_nonce_function_default(nonce32, msg32, key32, nullptr, nullptr, *extra);
}

} // namespace

namespace multy_core
Expand Down Expand Up @@ -124,10 +153,30 @@ class GolosPrivateKey : public PrivateKey
return make_clone(*this);
}

BinaryDataPtr sign(const BinaryData& /*data*/) const override
BinaryDataPtr sign(const BinaryData& data) const override
{
// TODO: implement signing.
return nullptr;
auto data_hash = do_hash<SHA2, 256>(data);

std::array<unsigned char, GOLOS_SIGNATURE_SIZE> result;
int recovery_id = 0;
unsigned int counter = 0;
do
{
secp256k1_ecdsa_signature signature;
if (!secp256k1_ecdsa_sign(secp_ctx(), &signature,
data_hash.data(), m_data.data(), extended_nonce_function, &counter, &recovery_id))
{
THROW_EXCEPTION("Failed to sign with private key.");
}

if (!secp256k1_ecdsa_signature_serialize_compact(secp_ctx(), result.data() + 1, &signature))
{
THROW_EXCEPTION("Failed to make compact size from signature.");
}
} while(!is_canonical_signature(result));

result.begin()[0] = GOLOS_RECOVERY_PARAM_COMPRESSED + GOLOS_RECOVERY_PARAM_COMPACT + recovery_id;
return make_clone(as_binary_data(result));
}

std::string to_string() const override
Expand Down
21 changes: 20 additions & 1 deletion multy_test/test_golos_account.cpp
Expand Up @@ -5,15 +5,20 @@
*/

#include "multy_test/serialized_keys_test_base.h"
#include "multy_core/src/golos/golos_account.h"


#include "multy_core/src/golos/golos_account.h"
#include "multy_core/src/api/key_impl.h"
#include "multy_core/golos.h"

#include "multy_test/utility.h"

#include "gtest/gtest.h"

namespace
{
using namespace multy_core::internal;
using namespace test_utility;
const BlockchainType GOLOS_MAINNET{BLOCKCHAIN_GOLOS, GOLOS_NET_TYPE_MAINNET};

const SerializedKeyTestCase GOLOS_KEYS[] =
Expand Down Expand Up @@ -112,4 +117,18 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(GOLOS_MAINNET),
::testing::ValuesIn(GOLOS_KEYS)));

GTEST_TEST(GolosTest, private_key_sign)
{
AccountPtr account;
make_account(BLOCKCHAIN_GOLOS, "5Hq2ZdSGZokcgLoNxNGL5kHKi4e3kUUCqorgFK6T6ka7KtSvYLj", reset_sp(account));
PrivateKeyPtr prv_key = account->get_private_key();
// binary serialize TX to sign golos private key
BinaryDataPtr signature = prv_key->sign(as_binary_data(from_hex("782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de1269466c1944189"
"fb3bb5a0102096d756c7479746573740b70617368616b6c7962696b010000000000000003474f4c4f5300000000")));
// signature generated form golos-core
ASSERT_EQ(as_binary_data(from_hex(
"1f2e6bb028760bacddd31dc9772e63240fd297ee2f9fcd29f3605aeb79f774fa4b7d1b4e6dc4a1cd6fd2d4e08b2ea2758680d6a5b1e49664522f391ff949b70018")),
*signature);
}

} // namespace

0 comments on commit 6ab6969

Please sign in to comment.