I start using openssl.
I want to use a public key to check a signature. But for now, I can not read my public key with openssl.
Here is my source code:
#include <iostream>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/err.h>
bool verifyPublicKey(const std::string &sRawPublicKey);
void printAllError();
int main(int argc, char* argv[])
{
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " PUBLIC KEY" << std::endl;
return EXIT_FAILURE;
}
std::string sPublicKey = argv[1];
std::cout << "Key: " << sPublicKey << std::endl;
bool bRes = verifyPublicKey(sPublicKey);
if (!bRes)
{
std::cerr << "verifyPublicKey failled" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
bool verifyPublicKey(const std::string &sRawPublicKey)
{
bool bRes = false;
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
unsigned char *p_RawPublicKey = new unsigned char[sRawPublicKey.length() + 1];
std::copy(sRawPublicKey.begin(), sRawPublicKey.end(), p_RawPublicKey);
const unsigned char *pubkey_raw_p = p_RawPublicKey;
o2i_ECPublicKey(&eckey, &pubkey_raw_p, sRawPublicKey.size());
if (!EC_KEY_check_key(eckey))
{
EC_KEY_free(eckey);
bRes = false;
printAllError();
}
else
{
EC_KEY_free(eckey);
bRes = true;
}
return bRes;
}
void printAllError()
{
while (ERR_peek_last_error() != 0)
{
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
}
}
I run it with the following public key:
3059301306072A8648CE3D020106082A8648CE3D03010703420004E297417036EB4C6404CC9C2AC4F28468DD0A92F2C9496D187D2BCA784DB49AB540B9FD9ACE0BA49C8532825954755EC10246A71AF2AEE9AEC34BE683CDDFD212
ASN.1 Decoder:
SEQUENCE {
SEQUENCE {
OBJECTIDENTIFIER 1.2.840.10045.2.1 (ecPublicKey)
OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
}
BITSTRING 0x04E297417036EB4C6404CC9C2AC4F28468DD0A92F2C9496D187D2BCA784DB49AB540B9FD9ACE0BA49C8532825954755EC10246A71AF2AEE9AEC34BE683CDDFD212
: 0 unused bit(s)
}
With the ASN.1, I notice that the key I use is in the correct format: 0x04 || HEX(x) || HEX(y) with z = 0x04.
The output of the program is as follows:
Key: 3059301306072A8648CE3D020106082A8648CE3D03010703420004E297417036EB4C6404CC9C2AC4F28468DD0A92F2C9496D187D2BCA784DB49AB540B9FD9ACE0BA49C8532825954755EC10246A71AF2AEE9AEC34BE683CDDFD212
error:10067066:elliptic curve routines:ec_GFp_simple_oct2point:invalid encoding
error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib
error:1010206A:elliptic curve routines:ec_key_simple_check_key:point at infinity verifyPublicKey failed
I'm lost. Do you have explanations?
Moreover, is it possible to go further by giving only x and y (without ASN.1 header).
Thank you
Looks like you should feed the raw point to function o2i_ECPublicKey(), without the ASN.1 framing.
Related
I wrote a small program in c++, and it doesn't have any error on compile time but when I run the program, I'm facing with an error.
Following is my code :
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include "QueType.h"
#include "StackType.h"
#include "tools.hpp"
#include <locale>
#include <list>
using namespace std;
bool isPalindrome(const string& stringToCheck)
{
string line2;
bool pal;
string wrdF;
stack<char> word1;
queue<char> word2;
char x,y;
line2=stringToCheck;
// make lowercase
for (size_t j=0; j< line2.length(); ++j)
{
line2[j] = tolower(line2[j]);
}
std::locale loc;
std::string str = line2 ;
std::string::size_type al=0;
wrdF = "";
std::string::size_type al2 = 0;
while ( (al<str.length()) ) {
if (std::isalnum(str[al])) {
wrdF += str[al];
al2++;
}
++al;
}
ItemType* items = new ItemType[al2];
strcpy(items,wrdF.c_str());
int oo=(int)al2;
for (int q=0;q<oo ;q++)
{
if (items[q] != ' ') {
word1.push(items[q]);
word2.push(items[q]);
}
}
pal = true;
while (!word1.empty() && !word2.empty())
{
x=word1.top();
y=word2.front();
if (x != y)
{
cout << "No palindrome" << endl;
pal=false;
break;
}
else
{
word1.pop();
word2.pop();
}
}
if (pal == true)
cout << " palindrome" << endl;
return(pal);
}
int main()
{
int row=0;
string line;
bool pali;
ifstream myfile ("palindrome-testfile.txt");
ofstream palin("palindromes.log");
ofstream nopalin("nopalindromes.log");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
// cout << line << '\n';
++row;
// cout<<row<<". ";
pali= isPalindrome(line);
if (pali)
{
palin << line << endl;
}
else
{
nopalin << line << endl;
}
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Please help me to resolve it. Thanks in advance.
Capture of error
As Igor Tandetnik pointed out the problem is with the ItemType pointer. Which also leaks memory.
I wrote a similar code that checks if a word is palindrome. The cppreference example for std::equal is a is_palindrome function.
I am not sure about why you need the step for std::isalnum. That one will return true for numbers too. std::isalpha will return true only if they are are letters, see cppreference doc for isalpha
Let me know if you need any clarifications.
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
bool isPalindrome(const std::string& str) {
return std::equal(str.begin(), str.begin() + str.size() / 2, str.rbegin());
}
int main() {
std::ifstream myfile("palindrome-testfile.txt");
if(!myfile.is_open()) {
std::cerr<< "Could not open file" << std::endl;
} else {
std::string word;
//operator >> will read words until you reach eof()
myfile >> word;
while(!myfile.eof()){
auto str = word;
//here I delete anything that is not alnum
str.erase(std::find_if(str.begin(), str.end(),
[](unsigned char c) { return !std::isalnum(c); }));
//Making all characters of the string lower case
std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); });
if(isPalindrome(str)) {
std::cout << "[" << str <<"] is palindrome" << std::endl;
} else {
std::cout << "[" << str <<"] is not palindrome" << std::endl;
}
myfile >> word;
}
myfile.close();
}
return 0;
}
This is my code:
int main (int argc, char *argv[])
{
typedef int KeyType;
typedef string MappedType;
typedef std::pair<KeyType, MappedType> ValueType;
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmAlloc;
typedef boost::unordered_map<KeyType, MappedType, boost::hash<KeyType>, std::equal_to<KeyType>, ShmAlloc> ShmHashMap;
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_or_create, "ContainerSharedMemory", 65536);
if(argc == 2 && string(argv[1]) == "clear")
{
boost::interprocess::shared_memory_object::remove("ContainerSharedMemory");
return 0;
}
ShmHashMap *hash_map = segment.find_or_construct<ShmHashMap>(boost::interprocess::unique_instance)(segment.get_segment_manager());
if(hash_map == NULL)
{
cout << "find_or_construct error" << endl;
return 0;
}
for(int i = 0; i < 5; ++i) {
ShmHashMap::iterator iter = hash_map->find(i);
if (iter == hash_map->end()) {
hash_map->insert(ValueType(i, "test"));
}
}
cout << "all..." << endl;
for(ShmHashMap::iterator iter = hash_map->begin(); iter != hash_map->end(); ++iter)
{
cout << iter->first << "|" << iter->second << endl;
}
cout << "end..." << endl;
return 0;
}
Everything is ok when MappedType is int, but a segment fault whit this code like this:
Rerun this program to access hash map in shared memory will coredump
----------------------------edit again----------------------------------
the problem about string is solved by sehe, thank you
and if i design a template class want to hide that detail, how could i do? if there is some perfect way
template<typename MappedType>
struct ComplexMappedType
{
ComplexMappedType(): t_access(0), t_expire(0) {}
ComplexMappedType(const MappedType& v, uint32_t a, uint32_t e): value(v), t_access(a), t_expire(e) {}
MappedType value;
uint32_t t_access;
uint32_t t_expire;
};
template <typename KeyType, typename MappedType>
class MMSHashMap
{
private:
typedef ComplexMappedType<MappedType> DataType;
typedef std::pair<KeyType, DataType> ValueType;
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmAlloc;
typedef boost::unordered_map<KeyType, DataType, boost::hash<KeyType>, std::equal_to<KeyType>, ShmAlloc> ShmHashMap;
public:
MMSHashMap(const std::string& name, size_t size, float e_thr, float e_scale);
~MMSHashMap() {delete pMemorySegment;}
size_t getMEMSize() { return pMemorySegment->get_size(); }
size_t getMEMFreeSize() { return pMemorySegment->get_free_memory(); }
bool get(const KeyType& key, MappedType& value, uint32_t& expire);
bool set(const KeyType& key, const MappedType& value, uint32_t expire);
bool del(const KeyType& key);
private:
void doCapacityElimination();
std::string _name;
boost::interprocess::managed_shared_memory* pMemorySegment;
boost::shared_mutex mutex, mutex_eliminate;
float fEliminateThreshold, fEliminateScale;
};
Of course. std::string allocates from the heap.
The heap is in your process address space, so any other process reading the same shared memory is going to get a wrong raw pointer there and invoke UB.
You need to use a shared-memory allocator with the strings too.
Live On Coliru (using mapped file for Coliru)
With shared memory:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/container/string.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
namespace bip = boost::interprocess;
int main (int argc, char *argv[])
{
typedef int KeyType;
typedef boost::container::basic_string<char, std::char_traits<char>, bip::allocator<char, bip::managed_shared_memory::segment_manager> > MappedType;
typedef std::pair<KeyType, MappedType> ValueType;
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmAlloc;
typedef boost::unordered_map<KeyType, MappedType, boost::hash<KeyType>, std::equal_to<KeyType>, boost::container::scoped_allocator_adaptor<ShmAlloc> > ShmHashMap;
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_or_create, "ContainerSharedMemory", 65536);
if(argc == 2 && std::string(argv[1]) == "clear")
{
boost::interprocess::shared_memory_object::remove("ContainerSharedMemory");
return 0;
}
ShmHashMap *hash_map = segment.find_or_construct<ShmHashMap>(boost::interprocess::unique_instance)(segment.get_segment_manager());
if(hash_map == NULL)
{
std::cout << "find_or_construct error" << std::endl;
return 0;
}
for(int i = 0; i < 5; ++i) {
ShmHashMap::iterator iter = hash_map->find(i);
if (iter == hash_map->end()) {
hash_map->insert(ValueType(i, MappedType { "hello", segment.get_segment_manager() }));
}
}
std::cout << "all..." << std::endl;
for(ShmHashMap::iterator iter = hash_map->begin(); iter != hash_map->end(); ++iter)
{
std::cout << iter->first << "|" << iter->second << std::endl;
}
std::cout << "end..." << std::endl;
}
Prints
all...
4|hello
3|hello
2|hello
1|hello
0|hello
end...
This is my header :
class my_router_client : public FIX8::my::mine_Router {
private:
mine_session_client& _session;
mutable std::vector<std::string> vSymbolList;
public:
my_router_client(mine_session_client& session) : _session(session) {}
virtual bool operator() (const FIX8::my::SecurityList *msg) const;
void sendToServer(FIX8::Message *);
void logout();
void itertool() const;
};
I am trying to save the data obtained from security list response to the vSymbolList vector. After handling security response I am trying to iterate through the vector by itertool method. But every time I end up with an empty vector. I tried printing the contents of the vector inside securitylist response function
virtual bool operator() (const FIX8::CX::SecurityList *msg) const;
and I am able to print the contents. Is it some kind of race condition inside threads?
this is the security list response handler
bool cx_router_client::operator() (const CX::SecurityList *msg) const
{
GroupBase *dad(msg->find_group< CX::SecurityList::NoRelatedSym >());
if (dad) {
for (size_t cnt(0); cnt < dad->size(); ++cnt) {
CX::Symbol symbol;
MessageBase *details(dad->get_element(cnt));
details->get(symbol);
string ss;
ss = symbol();
vSymbolList.push_back(ss);
// cout << "at :: :: " << vSymbolList[cnt] << endl;
}
cout << "no of symbol : " << vSymbolList.size() << endl;
hypersleep<h_seconds>(1);
}
return true;
}
This is the itertool method :
void my_router_client::itertool() const
{
cout << "symbol list vector size inside itertool:: " << vSymbolList.size() << endl;
stringstream ss;
ss << this_thread::get_id();
uint64_t id = stoull(ss.str());
cout << "Thread ID #### " << id << endl;
vector<string>::iterator it = this->vSymbolList.begin();
while (it != vSymbolList.end()) {
cout << *it << endl;
it++;
}
}
This is how I use the them in main :
int main()
{
const string conf_file("myfix_client.xml");
unique_ptr<ClientSessionBase> mc(new ClientSession<mine_session_client>(my::ctx(), conf_file, "DLD1"));
mc->start(false, next_send, next_receive, mc->session_ptr()->get_login_parameters()._davi());
hypersleep<h_seconds>(1);
my_router_client *test = new my_router_client(static_cast< mine_session_client& > (*mc->session_ptr()));
hypersleep<h_seconds>(1);
test->sendToServer(makeSecurityListRequest());
hypersleep<h_seconds>(1);
test->itertool();
while(1);
}
I am trying to go threw a vector of Student objects. If I find a matching ID to the one I am searching for it will display their info.
However, when I try to find a specific ID .compare isn't seeing a match even though it should.
My output: first line is the ID I am looking for, second is the current ID being looked at, then is the result of the compare.
a11111111
a22222222
-1
no match
a11111111
a11111111
-1
no match
Asked for more of the code so here is the entire program: (issue in displayID)
header file
#ifndef structures_h
#define structures_h
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <map>
using namespace std;
main program
#endif
typedef pair<string, string> Name; // first name, last name
typedef map<string, int> Grades; // map courses to scores
#include "struct.h"
class Student {
public:
void display(ostream& os) const;
void setId(string);
void setName(string, string);
void setGrades(string, int);
string getId();
string getName();
void getGrades();
bool operator<(const Student &rhs) const { return id_ < rhs.id_; }
private:
string id_; // e.g. "a22222222"
Name name_; // e.g. {"ned", "flanders"}
Grades grades_;
};
void Student::setId(string id) {
id_ = id;
}
string Student::getId() {
return id_;
}
void Student::setName(string first, string last) {
name_ = pair<string,string>(first, last);
}
string Student::getName() {
return get<0>(name_) + ' ' + get<1>(name_);
}
void Student::setGrades(string course, int score) {
grades_.insert(make_pair(course, score));
}
void Student::getGrades() {
for(auto it = grades_.begin(); it != grades_.end(); ++it) {
cout << it -> first << ' ' << it -> second << endl;
}
}
vector<Student> addStudent(int count, int x, vector<Student>& vStu, string file) {
string line, first, last;
ifstream infile(file);
while (getline(infile, line)) {
vStu.push_back(Student());
vStu[count].setId(line);
getline(infile, line);
istringstream iss(line);
if (!(iss >> first >> last)) {
cout << "failed to get name" << endl;
break;
}
vStu[count].setName(first, last);
getline(infile, line);
istringstream iss2(line);
if (!(iss2 >> x)) {
cout << "failed to get class number" << endl;
break;
}
for (int i = 0; i < x; i++) {
string sClass;
int grade;
getline(infile, line);
istringstream iss3(line);
if (!(iss3 >> sClass >> grade)) {
cout << "failed to get class and grade" << endl;
break;
}
vStu[count].setGrades(sClass, grade);
}
count++;
}
return vStu;
}
void display(vector<Student>& vStu) {
sort(vStu.begin(), vStu.end());
cout << endl;
int count = vStu.size();
for (int i = 0; i<count;i++) {
cout << vStu[i].getId() << endl;
cout << vStu[i].getName() << endl;
vStu[i].getGrades();
cout << endl;
}
}
void displayID(vector<Student>& vStu, string ID) {
int count = vStu.size();
string test;
ID = "a11111111";
for (int i = 0; i<count;i++) {
cout<< endl;
test = vStu[i].getId();
cout << ID << endl;
cout << test << endl;
cout << ID.compare(test) << endl;
if (ID.compare(test) == 0) {
cout << "match" << endl;
cout << vStu[i].getId() << endl;
cout << vStu[i].getName() << endl;
vStu[i].getGrades();
cout << endl;
} else {
cout << "no match" << endl;
}
}
cout << endl;
}
void mainMenu(vector<Student>& vStu) {
string input;
string word;
vector<string> com;
while(1) {
cout << "Enter command: ";
getline(cin,input);
istringstream iss(input);
while(iss >> word) {
com.push_back(word);
}
for (int i = 0; i < (int)com.size(); i++) {
transform(com[i].begin(), com[i].end(), com[i].begin(), ::tolower);
if (com[i] == "show") {
display(vStu);
} else if (com[i] == "showid") {
displayID(vStu, "a11111111");
}
}
com.clear();
}
}
int main(int argc, char *argv[]) {
vector<Student> vStu;
int count = 0, x = 0;
if (argc != 2) {
cout << "Incorrectly called" << endl;
cout << " " << argv[0] << ' ' << "<filename>" << endl;
return 1;
}
addStudent(count, x, vStu, argv[1]);
mainMenu(vStu);
}
The only possibility I see is that there is some whitespace at the end of the string that gets passed into your function. Try trimming the end of the string's like this this thread suggests before comparing and see if they still don't compare correctly.
I have SST files form Microsoft which I need to add to a java truststore.
The problem is all tools that Microsoft provides, add the certs from SST files to windows stores, so difficult to get PEM files form the SST files. If I run certmgr.exe (not certmgr.msc), I can get public key and all that but no cert (in pem or der), I saw bunch of VB scripts and powershell to load them using SST file into System.Security.Cryptography.X509Certificates.X509Certificate2Collection object, but still can't find a way to output as PEM (or der ) formated certificates.
Any suggestions?
S
You could use CAPI to open the SST file as a certificate store then enumerate over the certificates in the file. The following code does this and outputs the certificates in DER form to a file using a SHA1 hash of the certificate as a filename. The first argument is the output folder. The remaining one or more arguments are your SST files.
#include <stdio.h>
#include <tchar.h>
#include "windows.h"
#include "wincrypt.h"
#include "atlbase.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
std::string GetHexRepresentation(const unsigned char * Bytes, size_t Length)
{
std::ostringstream os;
os.fill('0');
os<<std::hex;
for(const unsigned char * ptr=Bytes;ptr<Bytes+Length;ptr++)
os<<std::setw(2)<<(unsigned int)*ptr;
std::string retval = os.str();
std::transform(retval.begin(), retval.end(),retval.begin(), ::toupper);
return retval;
}
BOOL WriteToFileWithHashAsFilename(PCCERT_CONTEXT pPrevCertContext, TCHAR* outputDir)
{
#undef RETURN
#define RETURN(rv) \
{ \
if( hHash ) CryptDestroyHash(hHash); \
if( hProv ) CryptReleaseContext(hProv, 0); \
return rv; \
}
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE byteFinalHash[20];
DWORD dwFinalHashSize = 20;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
std::cout << "CryptAcquireContext failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
std::cout << "CryptCreateHash failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptHashData(hHash, pPrevCertContext->pbCertEncoded, pPrevCertContext->cbCertEncoded, 0))
{
std::cout << "CryptHashData failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptGetHashParam(hHash, HP_HASHVAL, byteFinalHash, &dwFinalHashSize, 0))
{
std::cout << "CryptGetHashParam failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
std::string strHash = GetHexRepresentation(byteFinalHash, dwFinalHashSize);
std::wostringstream filename;
filename << outputDir << strHash.c_str() << ".der" <<std::ends;
FILE* f = _wfopen(filename.str().c_str(), L"wb+");
if(!f)
{
std::wcout << "Failed to open file for writing: " << filename.str().c_str() << std::endl;
RETURN(FALSE);
}
int bytesWritten = fwrite(pPrevCertContext->pbCertEncoded, 1, pPrevCertContext->cbCertEncoded, f);
fclose(f);
if(bytesWritten != pPrevCertContext->cbCertEncoded)
{
std::cout << "Failed to write file" << std::endl;
RETURN(FALSE);
}
RETURN(TRUE);
}
//usage: DumpCertsFromSst <output directory> <SST file 1> ... <SST file n>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
if(argc < 3)
{
std::cout << "At least two arguments must be provided: outputDirectory sstFile1 ... sstFileN etc" << std::endl;
return 0;
}
TCHAR* outputDir = argv[1];
for(int ii = 2; ii < argc; ++ii)
{
HANDLE hFile = NULL;
HCERTSTORE hFileStore = NULL;
LPCWSTR pszFileName = argv[ii];
//Open file
hFile = CreateFile(pszFileName, GENERIC_READ, 0, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
std::wcout << "Failed to open file: " << pszFileName << std::endl;
continue;
}
else
{
std::wcout << "Processing file: " << pszFileName << std::endl;
}
//open certificate store
hFileStore = CertOpenStore(CERT_STORE_PROV_FILE, 0, NULL, CERT_STORE_READONLY_FLAG, hFile);
if(NULL == hFileStore)
{
CloseHandle(hFile);
continue;
}
int count = 0;
PCCERT_CONTEXT pPrevCertContext = NULL;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
while(NULL != pPrevCertContext)
{
if(WriteToFileWithHashAsFilename(pPrevCertContext, outputDir))
++count;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
}
std::wcout << "Wrote " << count << " certificates" << std::endl;
CloseHandle(hFile);
CertCloseStore(hFileStore, 0);
}
return 1;
}