在数据库中存储公钥(C ++)

时间:2017-08-29 02:15:01

标签: c++ sqlite crypto++

我正在尝试将公钥(PK)和签名(由crypto ++库生成)存储到sqlite数据库。我首先将密钥编码为:

pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());

然后将它们存储在数据库中。但由于PK和签名具有特殊的特性,因此它们无法正确存储到数据库中。我用来存储的是:

char * PK = (char*) malloc (BC.trans[l].PK.length()+1);   //use malloc to manually manage the memory 
std::strcpy(PK,BC.trans[l].PK.c_str());
char *zSQL = sqlite3_mprintf("INSERT INTO BC (PK  VALUES ('%q');", PK);
rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);// executes the command in sqlite and returns the status (whether stroing was successful or not. 
free(PK);

应该将字符串复制到char,并且在将内容复制到char中时,问题恰好发生在此处。我认为它是因为字符串有特殊字符。对于哈希我有相同的跟随,但它的工作完全正常。仅限PK和签名。我也使用了memcpy和strncpy。没有什么可以做到这一点,仍然没有正确的密钥存储在数据库中。

有什么想法?

我已使用完整代码进行了更新。现在我可以存储PK,它似乎很好,但当我要求数据库删除一堆记录时,没有任何反应。这意味着再次出现问题。

以下是代码:

int Network_Nodes =10;   
int Block_Size=10;        
int BC_lenght=0;           
int Fin_BC_size =50; 

std::vector<CryptoPP::RSA::PrivateKey> prk;
std::vector<CryptoPP::RSA::PublicKey> pk;
std::vector<std::string> prev_t;           
struct Block {

    std::string block_hash;

    std::string block_num;

    struct transactions {
        std::string TransactionID;
        std::string previousTransactionID;
        std::string PK;
        std::string Sign;
    };
    std::vector<transactions> trans;
} BC;

int generatekey()
{    
    for (int i=0;i<Network_Nodes;i++)    
    {
        CryptoPP::AutoSeededRandomPool rng;
        CryptoPP::InvertibleRSAFunction param;
        param.GenerateRandomWithKeySize(rng,3072);
        CryptoPP::RSA::PrivateKey privatekey(param);
        CryptoPP::RSA::PublicKey publickey (param);
        prk.push_back(privatekey);
        pk.push_back(publickey);
    }
    return 0;
}
///////////////////////////////////////////////////////////////


void  initialization()
{    
    for (int i=0;i<=Network_Nodes;i++)
    {
        prev_t.push_back("NULL");
    }        

    //Creating database
    sqlite3 *db;
        char *zErrMsg = 0;
        int rc;
        char *sql;
        const char* data = "Callback function called";

        /* Open database */
        rc = sqlite3_open("RemovableBC.db", &db);
        if( rc ) {
                  fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
                  return;
               } else {
             //     fprintf(stdout, "Opened database successfully\n");
               }


        sql = "DROP TABLE BC";
        rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

        /* Create a table in the data base to be used for storing data. Create SQL statement */
          sql = "CREATE TABLE BC("  \
                "T_ID          TEXT    ," \
                "P_T_ID           TEXT   ," \
                "PK            BLOB    ," \
                "Signature        BLOB      ," \
                "Block_ID         TEXT       );";

          /* Execute SQL statement */
          rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
          if( rc != SQLITE_OK ){
                   fprintf(stderr, "SQL error: %s\n", zErrMsg);
                      sqlite3_free(zErrMsg);
                   } else {
             //         fprintf(stdout, "Table created successfully\n");
                   }
          sqlite3_close(db);    
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void fill_the_block(std::string block_content)
{        
        const char* data = "Callback function called";
        SHA256 hash;
        string digest;
        sqlite3 *db=NULL;
        char *sql;
        char *zErrMsg = 0;
        int rc;
        char sqlStr[2000];
        /* Open database */
        rc = sqlite3_open("RemovableBC.db", &db);
           if( rc ) {
                  fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
                  return;
                  } else {
                  //  fprintf(stdout, "Opened database successfully\n");
                 }
         StringSource s(block_content, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
         BC.block_hash=digest;
         for (int l=0 ; l<Block_Size ; l++)
               {
                                    char *begin = sqlStr;
                                    char *end = begin + sizeof(sqlStr);
                                    std::fill(begin, end, 0);
                                    char *zSQL = sqlite3_mprintf("INSERT INTO BC ( T_ID , P_T_ID , PK , Signature , Block_ID ) VALUES ('%q','%q','%q','%q','%q');", BC.trans[l].TransactionID.c_str() ,BC.trans[l].previousTransactionID.c_str() ,BC.trans[l].PK.c_str() ,BC.trans[l].Sign.c_str(),BC.block_hash.c_str());

                                     rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);

                                   sqlite3_free(zSQL);
                                   if( rc != SQLITE_OK ) {
                                       fprintf(stderr, "SQL error in populating : %s\n", zErrMsg);
                                       sqlite3_free(zErrMsg);
                                        } else {       
                 }


                                sqlite3_close(db);          //We close the connection we have with the database
}
///////////////////////////////////////////////////////////////////////////
void populate_bc ()
{        
        int generated_blocks=0;
        int stored_trans_in_block=0;                
        int node=0;                                               
        std::string block_content,trans_cont;                        
        std::string pkstring;  
        std::string signature;
        std::string mes ="This message is going to be singed";


        while (BC_lenght <=Fin_BC_size )
           {
            if (generated_blocks <= 10){
                 if (node >= Network_Nodes)
                        {
                            node=0; //cout << "step 4" <<endl;
                        }
                 if (stored_trans_in_block >= Block_Size)
                        {
                       cout << "block size is "<< BC_lenght<<endl;
                       fill_the_block(block_content);
                       BC_lenght++;
                       block_content.clear();
                       stored_trans_in_block=0;


                        for(int o=0; o<stored_trans_in_block;o++)
                                                {
                                                    BC.trans[o] = {};
                                                }
                                                 BC.trans = {};
                                                 BC ={};

                        }
                 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                 if (prev_t[node]=="NULL")
                        {
                          // cout << "We are populating on behafe of "<< node<< endl;
                          trans_cont="";
                          BC.trans.push_back(Block::transactions());

                          BC.trans[stored_trans_in_block].previousTransactionID ="NULL";
                        //  byte public_key[] = pk[node];

                          std::string endoced_pub;
                          Base64Encoder pubKeySink(new StringSink(endoced_pub));
                          pk[node].DEREncode(pubKeySink);
                      pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());
                          BC.trans[stored_trans_in_block].PK=endoced_pub;

                          CryptoPP::AutoSeededRandomPool rng;
                          CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(prk[node]);
                          CryptoPP::StringSource ss1(mes, true,
                                                   new CryptoPP::SignerFilter(rng, signer,
                                                                              new CryptoPP::StringSink(signature)
                                                          ) // SignerFilter
                                         ); // StringSource
                      //    cout << "step 1" <<endl;
                          BC.trans[stored_trans_in_block].Sign=signature;
                          trans_cont = "NULL" + pkstring + signature;
                          SHA256 hash;
                          string digest;
                          StringSource s(trans_cont, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
                      //    cout << "step 2" <<endl;
                          BC.trans[stored_trans_in_block].TransactionID=digest;
                          prev_t[node] =digest;                     // This keeps the previous transaction of each node in an array and thus we can later use to populate the BC
                          block_content+=digest;                    // This is to calculate the ID of the block which is the hash of all TIDs (hash of hash of all trnasctions)
                          node++;
                          stored_trans_in_block++;
                        //  cout << "step 3" <<endl;
                        }//end of  if (prev_t[node]=="NULL")
                    else
                        {// cout << "step 6" <<endl;
                                  trans_cont="";
                                  BC.trans.push_back(Block::transactions());

                                  BC.trans[stored_trans_in_block].previousTransactionID =prev_t[node];
                                std::string endoced_pub;
                                                          Base64Encoder pubKeySink(new StringSink(endoced_pub));
                                                          pk[node].DEREncode(pubKeySink);
                                                    //       pubKeySink.MessageEnd();

                              //    pk[node].BEREncode(CryptoPP::StringSink(pkstring).Ref());
                                  BC.trans[stored_trans_in_block].PK = endoced_pub;
                        //      BC.trans[stored_trans_in_block].PK= pk[node];
                                  CryptoPP::AutoSeededRandomPool rng;
                                  CryptoPP::RSASSA_PKCS1v15_SHA_Signer signer(prk[node]);
                                  CryptoPP::StringSource ss1(mes, true,
                                                           new CryptoPP::SignerFilter(rng, signer,
                                                                                      new CryptoPP::StringSink(signature)
                                                                  ) // SignerFilter
                                                 ); // StringSource
                                  BC.trans[stored_trans_in_block].Sign=signature;
                                  trans_cont = prev_t[node] + pkstring + signature;
                                  SHA256 hash;
                                  string digest;
                                  StringSource s(trans_cont, true, new HashFilter(hash, new HexEncoder(new StringSink(digest))));
                                  BC.trans[stored_trans_in_block].TransactionID=digest;
                                  prev_t[node] =digest;                     
                                  block_content+=digest;                    
                                  node++;
                                  stored_trans_in_block++;
                        }

                generated_blocks++;
            }


        else
        {

            generated_blocks=0;

        }
           }

}
//////////////////////////////////////////////////////////////////////////////////////

void remove_node (int i)
{


        std::string search_node;                    //This is the ID of the transaction that we need to search for in the BC,
        sqlite3 *db;

        std::string endoced_pub;
        Base64Encoder pubKeySink(new StringSink(endoced_pub));
         pk[i].DEREncode(pubKeySink);
    //    pubKeySink.MessageEnd();
        char *sql;
        int rc;
        char *zErrMsg = 0;

        const char* data = "Callback function called";
        /* Open database */
           rc = sqlite3_open("RemovableBC.db", &db);

           if( rc ) {
              fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
              return;
           } else {
            //  fprintf(stderr, "Opened database successfully\n");
           }
         /* Execute SQL statement */
        //   char *zSQL = sqlite3_mprintf("DELETE from BC");


            char * Search_NODE = (char*) malloc (endoced_pub.length()+1);
            std::strcpy(Search_NODE,endoced_pub.c_str());
                            std::strcpy(Search_NODE,search_node.c_str());

         //  char *zSQL = sqlite3_mprintf("DELETE from  BC  where PK = '%q';", Search_NODE);

                   char *zSQL = sqlite3_mprintf("UPDATE BC set Signature = null  and PK = null   where PK = '%q';", endoced_pub.c_str());
                   rc = sqlite3_exec(db, zSQL, callback, (void*)data, &zErrMsg);

cout<< endoced_pub.c_str()<<endl;


           if( rc != SQLITE_OK ) {
              fprintf(stderr, "SQL error in removing a record: %s\n", zErrMsg);
              sqlite3_free(zErrMsg);
           } else {
            //  fprintf(stdout, "Operation done successfully\n");
           }
           sqlite3_close(db);
           free(Search_NODE);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main() {

    auto initial = std::chrono::high_resolution_clock::now();
    generatekey();
    cout << "Keys are generated for " <<Network_Nodes << "  nodes..." << endl;

    clock_t begin_block_pup = clock();
    initialization();
    cout << "Initializing previous transaction vector..." << endl;

    //clock_t ti =clock();
    //double time = double (ti)/CLOCKS_PER_SEC;


    clock_t ti2 =clock();
        double time2 = double (ti2)/CLOCKS_PER_SEC;
    //cout << "second time is  " << done <<endl;
    populate_bc();
    cout << "BC has been populated with "<< BC_lenght <<" blocks..." << endl;
    return 0;
}

1 个答案:

答案 0 :(得分:1)

您的系统存在的问题是,您需要将PK数据存储为BLOB或将其编码为7位ASCII。

Sqlite具有一些国际化支持,并且可以将存储为字符串的原始二进制数据转换为不同的形式。 (例如UTF-8转换)

因此,要么在问题SO : sqlite blob

的答案中使用blob

或首先将字节转换为7位ascii(例如b64编码),然后存储数据。

记住,之后你需要对结果进行b64解码。