我正在尝试将公钥(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;
}
答案 0 :(得分:1)
您的系统存在的问题是,您需要将PK数据存储为BLOB或将其编码为7位ASCII。
Sqlite具有一些国际化支持,并且可以将存储为字符串的原始二进制数据转换为不同的形式。 (例如UTF-8转换)
因此,要么在问题SO : sqlite blob,
的答案中使用blob或首先将字节转换为7位ascii(例如b64编码),然后存储数据。
记住,之后你需要对结果进行b64解码。