LCOV - code coverage report
Current view: top level - src/test - key_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 181 181 100.0 %
Date: 2020-09-26 01:30:44 Functions: 42 42 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2012-2020 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <key.h>
       6             : 
       7             : #include <key_io.h>
       8             : #include <streams.h>
       9             : #include <test/util/setup_common.h>
      10             : #include <uint256.h>
      11             : #include <util/strencodings.h>
      12             : #include <util/string.h>
      13             : #include <util/system.h>
      14             : 
      15             : #include <string>
      16             : #include <vector>
      17             : 
      18             : #include <boost/test/unit_test.hpp>
      19             : 
      20          89 : static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj";
      21          89 : static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
      22          89 : static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
      23          89 : static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
      24          89 : static const std::string addr1 = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ";
      25          89 : static const std::string addr2 = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ";
      26          89 : static const std::string addr1C = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs";
      27          89 : static const std::string addr2C = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs";
      28             : 
      29          89 : static const std::string strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF";
      30             : 
      31             : 
      32          89 : BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
      33             : 
      34          95 : BOOST_AUTO_TEST_CASE(key_test1)
      35             : {
      36           1 :     CKey key1  = DecodeSecret(strSecret1);
      37           1 :     BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
      38           1 :     CKey key2  = DecodeSecret(strSecret2);
      39           1 :     BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
      40           1 :     CKey key1C = DecodeSecret(strSecret1C);
      41           1 :     BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
      42           1 :     CKey key2C = DecodeSecret(strSecret2C);
      43           1 :     BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
      44           1 :     CKey bad_key = DecodeSecret(strAddressBad);
      45           1 :     BOOST_CHECK(!bad_key.IsValid());
      46             : 
      47           1 :     CPubKey pubkey1  = key1. GetPubKey();
      48           1 :     CPubKey pubkey2  = key2. GetPubKey();
      49           1 :     CPubKey pubkey1C = key1C.GetPubKey();
      50           1 :     CPubKey pubkey2C = key2C.GetPubKey();
      51             : 
      52           1 :     BOOST_CHECK(key1.VerifyPubKey(pubkey1));
      53           1 :     BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
      54           1 :     BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
      55           1 :     BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));
      56             : 
      57           1 :     BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
      58           1 :     BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
      59           1 :     BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
      60           1 :     BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));
      61             : 
      62           1 :     BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
      63           1 :     BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
      64           1 :     BOOST_CHECK(key2.VerifyPubKey(pubkey2));
      65           1 :     BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));
      66             : 
      67           1 :     BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
      68           1 :     BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
      69           1 :     BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
      70           1 :     BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
      71             : 
      72           1 :     BOOST_CHECK(DecodeDestination(addr1)  == CTxDestination(PKHash(pubkey1)));
      73           1 :     BOOST_CHECK(DecodeDestination(addr2)  == CTxDestination(PKHash(pubkey2)));
      74           1 :     BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(PKHash(pubkey1C)));
      75           1 :     BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(PKHash(pubkey2C)));
      76             : 
      77          17 :     for (int n=0; n<16; n++)
      78             :     {
      79          16 :         std::string strMsg = strprintf("Very secret message %i: 11", n);
      80          16 :         uint256 hashMsg = Hash(strMsg);
      81             : 
      82             :         // normal signatures
      83             : 
      84          16 :         std::vector<unsigned char> sign1, sign2, sign1C, sign2C;
      85             : 
      86          16 :         BOOST_CHECK(key1.Sign (hashMsg, sign1));
      87          16 :         BOOST_CHECK(key2.Sign (hashMsg, sign2));
      88          16 :         BOOST_CHECK(key1C.Sign(hashMsg, sign1C));
      89          16 :         BOOST_CHECK(key2C.Sign(hashMsg, sign2C));
      90             : 
      91          16 :         BOOST_CHECK( pubkey1.Verify(hashMsg, sign1));
      92          16 :         BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2));
      93          16 :         BOOST_CHECK( pubkey1.Verify(hashMsg, sign1C));
      94          16 :         BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2C));
      95             : 
      96          16 :         BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1));
      97          16 :         BOOST_CHECK( pubkey2.Verify(hashMsg, sign2));
      98          16 :         BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1C));
      99          16 :         BOOST_CHECK( pubkey2.Verify(hashMsg, sign2C));
     100             : 
     101          16 :         BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1));
     102          16 :         BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2));
     103          16 :         BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1C));
     104          16 :         BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2C));
     105             : 
     106          16 :         BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1));
     107          16 :         BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2));
     108          16 :         BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1C));
     109          16 :         BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2C));
     110             : 
     111             :         // compact signatures (with key recovery)
     112             : 
     113          16 :         std::vector<unsigned char> csign1, csign2, csign1C, csign2C;
     114             : 
     115          16 :         BOOST_CHECK(key1.SignCompact (hashMsg, csign1));
     116          16 :         BOOST_CHECK(key2.SignCompact (hashMsg, csign2));
     117          16 :         BOOST_CHECK(key1C.SignCompact(hashMsg, csign1C));
     118          16 :         BOOST_CHECK(key2C.SignCompact(hashMsg, csign2C));
     119             : 
     120          16 :         CPubKey rkey1, rkey2, rkey1C, rkey2C;
     121             : 
     122          16 :         BOOST_CHECK(rkey1.RecoverCompact (hashMsg, csign1));
     123          16 :         BOOST_CHECK(rkey2.RecoverCompact (hashMsg, csign2));
     124          16 :         BOOST_CHECK(rkey1C.RecoverCompact(hashMsg, csign1C));
     125          16 :         BOOST_CHECK(rkey2C.RecoverCompact(hashMsg, csign2C));
     126             : 
     127          16 :         BOOST_CHECK(rkey1  == pubkey1);
     128          16 :         BOOST_CHECK(rkey2  == pubkey2);
     129          16 :         BOOST_CHECK(rkey1C == pubkey1C);
     130          16 :         BOOST_CHECK(rkey2C == pubkey2C);
     131          16 :     }
     132             : 
     133             :     // test deterministic signing
     134             : 
     135           1 :     std::vector<unsigned char> detsig, detsigc;
     136           1 :     std::string strMsg = "Very deterministic message";
     137           1 :     uint256 hashMsg = Hash(strMsg);
     138           1 :     BOOST_CHECK(key1.Sign(hashMsg, detsig));
     139           1 :     BOOST_CHECK(key1C.Sign(hashMsg, detsigc));
     140           1 :     BOOST_CHECK(detsig == detsigc);
     141           1 :     BOOST_CHECK(detsig == ParseHex("304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
     142           1 :     BOOST_CHECK(key2.Sign(hashMsg, detsig));
     143           1 :     BOOST_CHECK(key2C.Sign(hashMsg, detsigc));
     144           1 :     BOOST_CHECK(detsig == detsigc);
     145           1 :     BOOST_CHECK(detsig == ParseHex("3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
     146           1 :     BOOST_CHECK(key1.SignCompact(hashMsg, detsig));
     147           1 :     BOOST_CHECK(key1C.SignCompact(hashMsg, detsigc));
     148           1 :     BOOST_CHECK(detsig == ParseHex("1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
     149           1 :     BOOST_CHECK(detsigc == ParseHex("205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
     150           1 :     BOOST_CHECK(key2.SignCompact(hashMsg, detsig));
     151           1 :     BOOST_CHECK(key2C.SignCompact(hashMsg, detsigc));
     152           1 :     BOOST_CHECK(detsig == ParseHex("1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
     153           1 :     BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
     154           1 : }
     155             : 
     156          95 : BOOST_AUTO_TEST_CASE(key_signature_tests)
     157             : {
     158             :     // When entropy is specified, we should see at least one high R signature within 20 signatures
     159           1 :     CKey key = DecodeSecret(strSecret1);
     160           1 :     std::string msg = "A message to be signed";
     161           1 :     uint256 msg_hash = Hash(msg);
     162           1 :     std::vector<unsigned char> sig;
     163             :     bool found = false;
     164             : 
     165           1 :     for (int i = 1; i <=20; ++i) {
     166           1 :         sig.clear();
     167           1 :         BOOST_CHECK(key.Sign(msg_hash, sig, false, i));
     168           1 :         found = sig[3] == 0x21 && sig[4] == 0x00;
     169           1 :         if (found) {
     170           1 :             break;
     171             :         }
     172             :     }
     173           1 :     BOOST_CHECK(found);
     174             : 
     175             :     // When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries
     176             :     // We should see at least one signature that is less than 70 bytes.
     177             :     found = true;
     178             :     bool found_small = false;
     179         257 :     for (int i = 0; i < 256; ++i) {
     180         256 :         sig.clear();
     181         256 :         std::string msg = "A message to be signed" + ToString(i);
     182         256 :         msg_hash = Hash(msg);
     183         256 :         BOOST_CHECK(key.Sign(msg_hash, sig));
     184         256 :         found = sig[3] == 0x20;
     185         256 :         BOOST_CHECK(sig.size() <= 70);
     186         256 :         found_small |= sig.size() < 70;
     187         256 :     }
     188           1 :     BOOST_CHECK(found);
     189           1 :     BOOST_CHECK(found_small);
     190           1 : }
     191             : 
     192          95 : BOOST_AUTO_TEST_CASE(key_key_negation)
     193             : {
     194             :     // create a dummy hash for signature comparison
     195           1 :     unsigned char rnd[8];
     196           1 :     std::string str = "Bitcoin key verification\n";
     197           1 :     GetRandBytes(rnd, sizeof(rnd));
     198           1 :     uint256 hash;
     199           1 :     CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash);
     200             : 
     201             :     // import the static test key
     202           1 :     CKey key = DecodeSecret(strSecret1C);
     203             : 
     204             :     // create a signature
     205           1 :     std::vector<unsigned char> vch_sig;
     206           1 :     std::vector<unsigned char> vch_sig_cmp;
     207           1 :     key.Sign(hash, vch_sig);
     208             : 
     209             :     // negate the key twice
     210           1 :     BOOST_CHECK(key.GetPubKey().data()[0] == 0x03);
     211           1 :     key.Negate();
     212             :     // after the first negation, the signature must be different
     213           1 :     key.Sign(hash, vch_sig_cmp);
     214           1 :     BOOST_CHECK(vch_sig_cmp != vch_sig);
     215           1 :     BOOST_CHECK(key.GetPubKey().data()[0] == 0x02);
     216           1 :     key.Negate();
     217             :     // after the second negation, we should have the original key and thus the
     218             :     // same signature
     219           1 :     key.Sign(hash, vch_sig_cmp);
     220           1 :     BOOST_CHECK(vch_sig_cmp == vch_sig);
     221           1 :     BOOST_CHECK(key.GetPubKey().data()[0] == 0x03);
     222           1 : }
     223             : 
     224          12 : static CPubKey UnserializePubkey(const std::vector<uint8_t>& data)
     225             : {
     226          12 :     CDataStream stream{SER_NETWORK, INIT_PROTO_VERSION};
     227          12 :     stream << data;
     228          12 :     CPubKey pubkey;
     229          12 :     stream >> pubkey;
     230             :     return pubkey;
     231          12 : }
     232             : 
     233           6 : static unsigned int GetLen(unsigned char chHeader)
     234             : {
     235           6 :     if (chHeader == 2 || chHeader == 3)
     236           2 :         return CPubKey::COMPRESSED_SIZE;
     237           4 :     if (chHeader == 4 || chHeader == 6 || chHeader == 7)
     238           3 :         return CPubKey::SIZE;
     239           1 :     return 0;
     240           6 : }
     241             : 
     242          12 : static void CmpSerializationPubkey(const CPubKey& pubkey)
     243             : {
     244          12 :     CDataStream stream{SER_NETWORK, INIT_PROTO_VERSION};
     245          12 :     stream << pubkey;
     246          12 :     CPubKey pubkey2;
     247          12 :     stream >> pubkey2;
     248          12 :     BOOST_CHECK(pubkey == pubkey2);
     249          12 : }
     250             : 
     251          95 : BOOST_AUTO_TEST_CASE(pubkey_unserialize)
     252             : {
     253           7 :     for (uint8_t i = 2; i <= 7; ++i) {
     254           6 :         CPubKey key = UnserializePubkey({0x02});
     255           6 :         BOOST_CHECK(!key.IsValid());
     256           6 :         CmpSerializationPubkey(key);
     257           6 :         key = UnserializePubkey(std::vector<uint8_t>(GetLen(i), i));
     258           6 :         CmpSerializationPubkey(key);
     259           6 :         if (i == 5) {
     260           1 :             BOOST_CHECK(!key.IsValid());
     261             :         } else {
     262           5 :             BOOST_CHECK(key.IsValid());
     263             :         }
     264           6 :     }
     265           1 : }
     266             : 
     267          89 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.15