MinGW and adding a Library - c++

I want to use this library with MinGW and i've been trying to get the example to work.
Is this possible? I've had a look at using this but i've still not managed to do it.
Also, i'm welcome to alternative suggestions to sha1 hashing a string.
These are the errors I get when i try to compile sha1.cpp or the example program:
sha1.h:29:17: error: extra qualification 'SHA1::' on member 'lrot' [-fpermissive]
sha1.h:30:15: error: extra qualification 'SHA1::' on member 'storeBigEndianUint32' [-fpermissive]
sha1.h:31:15: error: extra qualification 'SHA1::' on member 'hexPrinter' [-fpermissive]
Thanks.
Part 2
#include <fstream>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include "sha1.h"
using namespace std;
int main(int argc, char *argv[])
{
const char* BYTES;
ifstream myFile("word.txt");
if (! myFile)
{
cout << "Error openning file" << endl;
return -1;
}
while (! myFile.eof())
{
getline(myFile, BYTES);
cout << BYTES << endl;
SHA1* sha1 = new SHA1();
sha1->addBytes(BYTES, strlen(BYTES));
unsigned char* digest = sha1->getDigest();
sha1->hexPrinter(digest, 20);
delete sha1;
free(digest);
}
myFile.close();
return 0;
}

I can vouch for Crypto++ and Botan. Both are great crypto libraries and I've used them both with Windows and mingw. They do sha1 and other hashes.

The problem is in the extra "SHA1::" in the following lines in the file SHA1.h:
static Uint32 SHA1::lrot( Uint32 x, int bits );
static void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num );
static void SHA1::hexPrinter( unsigned char* c, int l );
They should be modified into
static Uint32 lrot( Uint32 x, int bits );
static void storeBigEndianUint32( unsigned char* byte, Uint32 num );
static void hexPrinter( unsigned char* c, int l );
This because the functions are being defined in the class SHA1 and is unnecessary to define again that they are in SHA1. Note that the same unmodified file may be accepted by Visual Studio (I had the same problem few years ago)

Related

Strange behavior using CString in swscanf directly

I have one problem with CString and STL's set.
It looks a bit strange to use CString and STL together, but I tried to be curious.
My code is below:
#include "stdafx.h"
#include <iostream>
#include <set>
#include <atlstr.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t line[1024] = {0};
FILE * pFile = _wfopen(L"F:\\test.txt", L"rt");
set<CString> cstr_set;
while (fgetws(line, 1024, pFile))
{
CString cstr;
swscanf(line, L"%s\n", cstr);
cstr_set.insert(cstr);
}
fclose(pFile);
cout << "count" << cstr_set.size();
return 0;
}
The contents of the test.txt is:
13245
123
2344
45
After the loop ends, cstr_set contains only one value.
It works as if cstr is static or const variable.
What is the problem?
A CString is a Microsoft implementation wrapping a character array into a C++ object to allow simpler processing.
But, swscanf is a good old C function that knows nothing about what a CString is: it just expects its arguments to be large enough to accept the decoded values. It should never be directly passed a CString.
The correct way would be:
...
#include <cstring>
...
while (fgetws(line, 1024, pFile))
{
line[wcscspn(line, L"\n")] = 0; // remove an optional end of line
CString cstr(line);
cstr_set.insert(cstr);
}
...

Am I implementing strcpy_s incorrectly?

I am getting this error message from the C++ compiler:
'strcpy_sā€™ was not declared in this scope
I have gone through many blogs, read documentation, trying to correct the issue. This is an assignment for secure coding, although I am not a programmer.
Here is my code:
#include <iostream>
#include <string.h>
using namespace std;
void sampleFunc(char inStr[])
{
char buf[10];
buf[9] ='\0';
strcpy_s(buf, inStr);
cout << "\n" << buf << "\n";
return;
}
int main(){
char inStr[10];
cout << "Enter String: ";
cin >> inStr;
sampleFunc(inStr);
}
worth mentioning, apart from the argument count to strcpy_s , the reference manual says
strcpy_s is only guaranteed to be available if STDC_LIB_EXT1 is
defined by the implementation and if the user defines
STDC_WANT_LIB_EXT1 to the integer constant 1 before including string.h.
Thus the right usage is something as mentioned in the reference link above
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
// and somewhere the the code
#ifdef __STDC_LIB_EXT1__
set_constraint_handler_s(ignore_handler_s);
int r = strcpy_s(dst, sizeof dst, src);
printf("dst = \"%s\", r = %d\n", dst, r);
r = strcpy_s(dst, sizeof dst, "Take even more tests.");
printf("dst = \"%s\", r = %d\n", dst, r);
#endif
The problem is that strcpy_s() takes three arguments, and you are only providing two.
errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
Unlike strcpy(), strcpy_s() requires that you provide the size of the destination buffer.
Try making the following modification to sampleFunc():
void sampleFunc(char inStr[])
{
char buf[10];
buf[9] ='\0';
strcpy_s(buf, 9, inStr);
cout <<"\n" <<buf<<"\n";
return;
}

Dynamically generate protobuf Message and return a pointer to it

First of all I'm not very experienced with C++, so maybe I'm overseeing something here.
I'm trying to dynamically generate protobuf Messages from .proto files with the following code:
int init_msg(const std::string & filename, protobuf::Arena* arena, protobuf::Message** new_msg){
using namespace google::protobuf;
using namespace google::protobuf::compiler;
DiskSourceTree source_tree;
source_tree.MapPath("file", filename);
MuFiErCo error_mist;
Importer imp(&source_tree, &error_mist);
printf("Lade Datei:%s \n", filename.c_str());
const FileDescriptor* f_desc = imp.Import("file");
const Descriptor* desc = f_desc->FindMessageTypeByName("TestNachricht");
const Message* new_msg_proto = dmf.GetPrototype(desc);
*new_msg = new_msg_proto->New(arena);
//Debug
cout << (*new_msg)->GetTypeName() << endl;
return 0;
}
int main(int argc, char* argv[]){
protobuf::Arena arena;
protobuf::Message *adr2, *adr1;
init_msg("schema-1.proto", &arena, &adr1);
init_msg("schema-1.proto", &arena, &adr2);
printf("MSG_Pointer: %p, %p\n", adr1, adr2);
cout << adr1->GetTypeName() << endl;
arena.Reset();
return 0;
}
I thought if i use Arena, the new Message is also available outside the scope of the function.
But there is always a segfault if i try to access the Message.
I guess it's a simple error, but I couldn't figure out, how to solve this.
Here is the ouput:
Lade Datei:schema-1.proto
packet.TestNachricht
Lade Datei:schema-1.proto
packet.TestNachricht
MSG_Pointer: 0x1b293b0, 0x1b287f0
Speicherzugriffsfehler (Speicherabzug geschrieben)
The problem, I think, is that FileDescriptor et al are destroyed when
init_msg returns, leaving the newly created message with no way to
interrogate its .proto definition. You'd need to move Importer
instance to main and keep it alive. This has nothing to do with
arenas. ā€“ Igor Tandetnik
That was the solution.
Here is some working example code
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/arena.h>
using namespace std;
using namespace google::protobuf;
class MuFiErCo : public compiler::MultiFileErrorCollector
{
public:
void AddError(const string & filename, int line, int column, const string & message){
printf("Err: %s\n", message.c_str());
}
void AddWarning(const string & filename, int line, int column, const string & message){
printf("Warn: %s\n", message.c_str());
}
};
compiler::Importer* init_proto_dir(Arena* arena, const std::string &root_dir){
using namespace compiler;
static DiskSourceTree source_tree;
source_tree.MapPath("", root_dir);
static MuFiErCo error_mist;
static Importer* imp = Arena::Create<Importer>(arena, &source_tree, &error_mist);
return imp;
}
void init_proto_def(compiler::Importer* imp, const std::string &proto_file){
using namespace compiler;
imp->Import(proto_file);
return;
}
Message* init_msg(compiler::Importer* imp, Arena* arena, const std::string &msg_name){
const DescriptorPool* pool = imp->pool();
static DynamicMessageFactory dmf;
const Descriptor* desc = pool->FindMessageTypeByName(msg_name);
const Message* msg_proto = dmf.GetPrototype(desc);
return msg_proto->New(arena);
}
int set_value(Message* msg, const char* value_name, unsigned long int value){
const Message::Reflection* reflec = msg->GetReflection();
const Descriptor* desc = msg->GetDescriptor();
const FieldDescriptor* fdesc = desc->FindFieldByName(value_name);
reflec->SetUInt64(msg, fdesc, value);
return 0;
}
int main(int argc, char* argv[]){
Arena arena;
compiler::Importer* imp = init_proto_dir(&arena, "");
init_proto_def(imp, "schema-1.proto");
Message* msg = init_msg(imp, &arena, "packet.TestNachricht");
set_value(msg, "zahl", 23434);
cout << msg->DebugString() << endl;
return 0;
}

Generate HMAC SHA256 hash using key in C++

I am looking for some function or a way that would return HMAC SHA256 hash in C++ using secret key. I have seen documentation of Crypto++ and OpenSSL but it does not accept an extra parameter of secret key for computation. Can someone help me by providing some info, code snippets or links.
You can use POCO library
Sample code:
class SHA256Engine : public Poco::Crypto::DigestEngine
{
public:
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 32
};
SHA256Engine()
: DigestEngine("SHA256")
{
}
};
Poco::HMACEngine<SHA256Engine> hmac{secretKey};
hmac.update(string);
std::cout << "HMACE hex:" << Poco::DigestEngine::digestToHex(hmac.digest()) << std::endl;// lookout difest() calls reset ;)
Sample integration with POCO using cmake install:
mkdir build_poco/
cd build_poco/ && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install ../poco/
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.8)
PROJECT(SamplePoco)
SET(CMAKE_CXX_STANDARD 14)
SET(SOURCE_FILES
src/main.cpp
)
SET(_IMPORT_PREFIX lib/build_poco/install)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoFoundationTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoNetTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoJSONTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoXMLTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoCryptoTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoUtilTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoNetSSLTargets.cmake)
ADD_EXECUTABLE(SamplePoco ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(SamplePoco
Poco::Foundation
Poco::Crypto
Poco::Util
Poco::JSON
Poco::NetSSL
)
TARGET_INCLUDE_DIRECTORIES(SamplePoco PUBLIC src/)
Sample implementation used here: https://github.com/gelldur/abucoins-api-cpp
Following is a sample of function to generate SHA256-HMAC using Crypto++
#include <string>
#include <string_view>
#include <cryptopp/filters.h>
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::HashFilter;
#include <cryptopp/hmac.h>
using CryptoPP::HMAC;
#include <cryptopp/sha.h>
using CryptoPP::SHA256;
std::string CalcHmacSHA256(std::string_view decodedSecretKey, std::string_view request)
{
// Calculate HMAC
HMAC<SHA256> hmac(reinterpret_cast<CryptoPP::byte const*>(decodedSecretKey.data()), decodedSecretKey.size());
std::string calculated_hmac;
auto sink = std::make_unique<StringSink>(calculated_hmac);
auto filter = std::make_unique<HashFilter>(hmac, sink.get());
sink.release();
StringSource(reinterpret_cast<CryptoPP::byte const*>(request.data()), request.size(), true, filter.get()); // StringSource
filter.release();
return calculated_hmac;
}
#include <iostream>
int main() {
std::cout << CalcHmacSHA256("key", "data");
}
The source is CME iLink2 specification
For consistency, following is a sample of function to generate SHA256-HMAC using OpenSSL
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <string>
#include <string_view>
#include <array>
std::string CalcHmacSHA256(std::string_view decodedKey, std::string_view msg)
{
std::array<unsigned char, EVP_MAX_MD_SIZE> hash;
unsigned int hashLen;
HMAC(
EVP_sha256(),
decodedKey.data(),
static_cast<int>(decodedKey.size()),
reinterpret_cast<unsigned char const*>(msg.data()),
static_cast<int>(msg.size()),
hash.data(),
&hashLen
);
return std::string{reinterpret_cast<char const*>(hash.data()), hashLen};
}
For the record, I like Crypto++ better as in case of Crypto++ generated binary is smaller. The drawback is that Crypto++ does not have a CMake module.
OpenSSL docs for HMAC, clearly state the requirement of a 'key' as part of context initialization.
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md, ENGINE *impl);
HMAC() computes the message authentication code of the n bytes at d
using the hash function evp_md and the key key which is key_len bytes
long.
You can use cpp-cryptlite to generate HMAC SHA256 hash, Following is the code snippet:
std::string src_str = "abcdefg";
std::string secret_key = "xxxxxx"; // this value is an example
boost::uint8_t digest[32]; // cryptlite::sha256::HASH_SIZE
cryptlite::hmac<cryptlite::sha256>::calc(src_str, secret_key, digest);
// and digest is the output hash
I had to modify #DmytroOvdiienko's answer a bit to get hexadecimal output:
#include <iomanip>
...
std::string CalcHmacSHA256(std::string_view decodedKey, std::string_view msg)
{
std::array<unsigned char, EVP_MAX_MD_SIZE> hash;
unsigned int hashLen;
HMAC(
EVP_sha256(),
decodedKey.data(),
static_cast<int>(decodedKey.size()),
reinterpret_cast<unsigned char const*>(msg.data()),
static_cast<int>(msg.size()),
hash.data(),
&hashLen
);
std::stringstream out;
for (unsigned int i=0; i < hashLen; i++) {
out << std::setfill('0') << std::setw(2) << std::right << std::hex << (int)hash.data()[i];
}
return out.str();
}
int main(int, char**) {
std::string key = "ESiFg448MqOmhQyxbt6HEHHPnAA1OE8nX0o9ANIVMIvWLISQS0MivDrkZvnBxMEI";
std::string msg = "foo";
std::string_view key_view{key};
std::string_view msg_view{msg};
std::cout << CalcHmacSHA256(key_view, msg_view) << std::endl;
}
The <iomanip>, setfill, setw, right are needed to make sure single-digit hex values are prefixed with a 0. An alternative is to use boost:
#include <boost/format.hpp>
...
out << boost::format("%02x") % (int)hash.data()[i];

Visual Studio 2008 C++ misreporting memory address location

I'm attempting to debug a stack overwrite (no pun intended) corruption problem with some c/c++ code in Visual Studio 2008.
When I compile the solution in win32 debug mode, I'm able to run the debugger and see a class get instantiated.
In the constructor call, we initialize some fixed length char[] member variables using memset.
If I use printf to print the memory location of the member variable, I get a value that is exactly 14 bytes past what the VS2008 watch/local var window reports as the memory location.
How does VS calculate what it thinks the memory address is of a variable?
Edit: I have compiled with Run Time Check options, and what I see is "Run-time Check Failure #2 - stack around variable 'varName' was corrupted.
Edit 3: Here is the abbreviated source
Header file:
//////////////////////////////////////////////////////////////////////
#include "commsock.h"
#include "buffer.h"
#include "BufferedReader.h"
#define AUTHTYPE_PASSKEY 1
#define AUTHTYPE_PAGER 2
#define AUTHTYPE_PASSWORD 3
#define AUTHTYPE_RADIUS 4
#define AUTHTYPE_INFOCARD_RO 5
#define AUTHTYPE_INFOCARD_CR 6
#define AUTHSTATE_NOT_LOGGED_IN 0
#define AUTHSTATE_IDENTIFIED 1
#define AUTHSTATE_AUTHENTICATED 2
#define AUTHSTATE_MAX_FAILS 32
#define AUTHSTATE_NO_LOG 65536
class PRClientSession {
public:
PRClientSession();
virtual ~PRClientSession();
void Reset();
BOOL BeginAuth(LPCSTR szUserID, LPCSTR szClientIP, LPCSTR szOtherUserID="");
BOOL CompleteAuth(LPCSTR szResponse);
BOOL Logoff();
BOOL DetachAsync();
BOOL Detach();
BOOL Attach(const char *authstr=NULL);
BOOL Connected(){return m_Socket.Connected();};
BOOL EncryptText(char *pPassword, char *pOut, char *pKey);
BOOL EncryptText(char *pPassword, char *pOut);
BOOL DecryptText(char *pPassword, char *pOut, char *pKey);
BOOL DecryptText(char *pPassword, char *pOut);
LPCSTR Error(LPCSTR szErr=NULL){if (szErr)strncpy_s(m_szError,szErr,sizeof(m_szError));return m_szError;};
LPCSTR Challenge(LPCSTR szChal=NULL){if (szChal)strncpy_s(m_szChallenge,szChal,sizeof(m_szChallenge));return m_szChallenge;};
LPCSTR UserID(LPCSTR szUID=NULL){if (szUID)strncpy_s(m_szUserID,szUID,sizeof(m_szUserID));return m_szUserID;};
LPCSTR SessionID(LPCSTR szSID=NULL){if (szSID)strncpy_s(m_szSessionID,szSID,sizeof(m_szSessionID));return m_szSessionID;};
LPCSTR SessionLogID(LPCSTR szSLID=NULL){if (szSLID)strncpy_s(m_szSessionLogID,szSLID,sizeof(m_szSessionLogID));return m_szSessionLogID;};
LPCSTR SessionStateID(LPCSTR szSSID=NULL){if (szSSID)strncpy_s(m_szSessionStateID,szSSID,sizeof(m_szSessionStateID));return m_szSessionStateID;};
int AuthType(int iType=-1){if (iType != -1)m_iAuthType = iType;return m_iAuthType;};
int SendRequest(LPCSTR szType, ...);
int Write(char *szBuf, int iLen=-1);
int Read(char *szBuf, int iLen, int iTimeout=-1);
BOOL ReadResponse(int iBlock=FALSE);
int ReadResponseTimeout(int iBlock) ;
BOOL GetField(LPCSTR szField, char *szBuf, int iLen, int total=-1);
BOOL GetField(LPCSTR szField, int &iBuf );
char *GetData(){return m_pData;};
int GetDataSize(){return m_iDataSize;}
char *GetMessage(){return m_pMessage;};
SOCKET getSocket(){return m_Socket.getSocket();}
private:
BOOL LoadConfig();
BOOL GetMsgField(LPCSTR szIn, LPCSTR szSrch, char *szBuf, int iLen, int total=-1);
int ReadMessage( char *buf, int len, const char *terminator = NULL );
public:
bool sendCommand(char* szCommand, char *szArglist);
LPCSTR ReplyMessage(){ return m_szReplyMessage; }
int IsRadiusChallenge(){ return m_iIsRadiusChallenge; }
static char PRIISMS_USER_TAG[];
static char DEST_USER_TAG[];
static char RADIUS_USER_TAG[];
static char RADIUS_PASSWORD_TAG[];
static char GENERATE_LOGIN[];
static char VALIDATE_LOGIN[];
static char PR_RADIUS_GENERATED[];
private:
BOOL doConnect();
// Response reader vars...
char *m_pMessage;
char *m_pData;
Buffer m_Buf;
BOOL m_bLoaded;
BufferedReader m_reader;
Buffer m_ReqBuf;
CCommSocket m_Socket;
char m_szServer[128];
int m_iServerPort;
char m_szError[128];
int m_iAuthState;
int m_iDataSize;
int m_iAuthType;
char m_szChallenge[1024];
char m_szUserID[64];
char m_szSessionID[64];
char m_szSessionLogID[64];
char m_szSessionStateID[64];
char m_szSessionSecret[16];
long m_RequestID;
int m_iIsRadiusChallenge;
char m_szReplyMessage[1024];
};
and the source code with constructor...
#include "stdafx.h"
#include "PRclntsn.h"
#include "iondes.h"
#include "prsystemparameters.h"
#include "prsessionlog.h"
#include "util.h"
#include "PRClntSn.h"
#include <string>
using namespace std;
#define LoadConfigFailedMsg "Unable to retrieve database configuration entries."
#ifndef AUTH_TYPE_RADIUS
#define AUTH_TYPE_RADIUS 4
#endif
//------------------------------------------------------------------------------------
// initialize static members
char PRClientSession::DEST_USER_TAG[] = "DEST_USER=";
char PRClientSession::PRIISMS_USER_TAG[] = "PRIISMS_USER=";
char PRClientSession::RADIUS_USER_TAG[] = "RADIUS_USER=";
char PRClientSession::RADIUS_PASSWORD_TAG[] = "RADIUS_PASSWORD=";
char PRClientSession::GENERATE_LOGIN[] = "GENERATE_LOGIN";
char PRClientSession::VALIDATE_LOGIN[] = "VALIDATE_LOGIN";
char PRClientSession::PR_RADIUS_GENERATED[] = "PR_RADIUS_GENERATED";
PRClientSession::PRClientSession()
{
Reset();
}
void PRClientSession::Reset()
{
//LOG4CXX_TRACE(mainlogger, CLASS_METHOD_TAG);
printf("m_szServer mem location: %p", (void *)&m_szServer);
memset(m_szServer, 0, sizeof(m_szServer));
m_iServerPort = 0;
memset(m_szError, 0, sizeof(m_szError));
m_iAuthState = 0;
m_iDataSize = 0;
m_iAuthType = 0;
memset(m_szChallenge, 0, sizeof(m_szChallenge));
memset(m_szUserID, 0, sizeof(m_szUserID));
memset(m_szSessionID, 0, sizeof(m_szSessionID));
memset(m_szSessionLogID, 0, sizeof(m_szSessionLogID));
memset(m_szSessionStateID, 0, sizeof(m_szSessionStateID));
memset(m_szSessionSecret, 0, sizeof(m_szSessionSecret) );
// memset(m_szReadBuf, 0, sizeof(m_szReadBuf));
m_RequestID = 0;
m_iIsRadiusChallenge = 0;
memset(m_szReplyMessage, 0, sizeof(m_szReplyMessage));
m_reader.setComm(&m_Socket);
}
Output of printf:
m_szServer mem location: 01427308
Visual Studio 2008 Locals window
m`_szServer 0x014272fa "" char [128]`
It's off by 14... and when the code actually runs the very first memset, it does so starting with address 7308, not 72fa. It basically tramples contiguous memory regions (and thus, variables)
The debugger inserts extra space. This space is set to a pre-defined value, and if it's changed, the debugger knows that something has gone wrong. It's normal for compilers and debuggers to insert space that serves no apparent purpose.
If you have used a fixed-size char[], that immediately signals to me as a problem, since there's no explicit encapsulation. You could use a custom array type (such as boost::array) to write your own buffer overrun detection code. If you throw at this time, you will get a stack trace.
This is (probably) not going to fix your bug, but I would try to avoid C-style arrays if you can.
Unless you have some compelling reason to use the fixed-length arrays, replace them with std::vector which will be filled with 0x00 by default.
so instead of
const size_t MYCLASS::BUFLEN(16);
class myClass {
public:
myClass()
{
memset(buffer, 0, BUFLEN);
}
private:
static const size_t BUFLEN;
char buffer[BUFLEN];
};
you have
const size_t MYCLASS::BUFLEN(16);
class myClass {
public:
myClass() : buffer(BUFLEN)
{
memset(buffer, 0, BUFLEN);
}
private:
static const size_t BUFLEN;
std::vector<char> buffer;
};