I am new to crypto++ and just follow an example from its cryptest project (test.cpp). I generated both public and private keys using RSA. I try to use the keys, exactly as in the example. It works perfectly well in crypto++ own project and generates unhandled exception in mine. Below is the basic code, which breaks at decryption stage. any suggestions on why?
#include "stdafx.h"
#include <core/osrng.h>
#include <core/modes.h>
#include <core/hex.h>
#include <core/files.h>
#include <core/rsa.h>
#include <core/sha.h>
#include <core/cryptlib.h>
#include <iostream>
using namespace CryptoPP;
using namespace std;
static OFB_Mode<AES>::Encryption s_globalRNG;
RandomNumberGenerator & GlobalRNG()
{
return s_globalRNG;
}
string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
{
FileSource pubFile(pubFilename, true, new HexDecoder);
RSAES_OAEP_SHA_Encryptor pub(pubFile);
RandomPool randPool;
randPool.IncorporateEntropy((byte *)seed, strlen(seed));
string result;
StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
return result;
}
string RSADecryptString(const char *privFilename, const char *ciphertext)
{
FileSource privFile(privFilename, true, new HexDecoder);
RSAES_OAEP_SHA_Decryptor priv(privFile);
string result;
StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
char privFilename[128] = "pri4096";
char pubFilename[128] = "pub4096";
char seed[1024] = "seed";
char message[1024] = "test";
try
{
string ciphertext = RSAEncryptString(pubFilename, seed, message);
string decrypted = RSADecryptString(privFilename, ciphertext.c_str());
}
catch(CryptoPP::Exception &e)
{
cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
}
return 0;
}
In my project the program breaks at line
StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
And debugger points to rjindael.cpp, function AESNI_Enc_Block, line 1005.
As pointed out by Yakk, I missed initialisation of the variable s_globalRNG. The following code fixes my problem.
//just below main()
std::string seed2 = IntToString(time(NULL));
seed2.resize(16);
s_globalRNG.SetKeyWithIV((byte *)seed2.data(), 16, (byte *)seed2.data());
thanks a lot!
Related
We are using cryptopp library. We are using the below coding. Encryption is working file without any issue and we are able to get the cipher text. But getting an error while decrypting as "Block padding found". What could be the issue...?
#include <iostream>
#include <string>
using namespace std;
#include "cryptlib.h"
#include "filters.h"
#include "files.h"
#include "modes.h"
#include "hex.h"
#include "aes.h"
#include "osrng.h"
using namespace CryptoPP;
using CryptoPP::AutoSeededRandomPool;
class cspl_crypto{
public:
cspl_crypto();
byte* generate_block(int size);
char* encrypt_rijndael(byte[], byte[], int, char*, int);
char* decrypt_rijndael(byte[], byte[], int, char*, int);
string readFile();
void writeFile(string);
};
cspl_crypto::cspl_crypto()
{
}
int main(int argc, char* argv[])
{
vector<byte> plain;
cspl_crypto ccrypto;
AutoSeededRandomPool prng;
byte key[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));
byte iv[AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
Converting string to char *
string str("testing"); //ccrypto.readFile()
char plainArray[str.size()];
strcpy(plainArray, str.c_str());
char* cipher = ccrypto.encrypt_rijndael(key, iv, sizeof(key), plainArray,
sizeof(plainArray));
//char cipherCharArray[cipherText.size()];
// strcpy(cipherCharArray, cipherText.c_str());
char* recover = ccrypto.decrypt_rijndael(key, iv, sizeof(key), cipher,
sizeof(cipher));
// cout << "Recovered text: " << recoverText << endl;
return 0;
}
Encryption Block:
char* cspl_crypto::encrypt_rijndael(byte key[], byte iv[], int keysize, char
plainText[], int plainTextSize){
vector<byte> cipher;
std::vector<byte> plain(plainText, plainText + plainTextSize);
CBC_Mode<AES>::Encryption enc;
enc.SetKeyWithIV(key, keysize, iv, keysize);
// Make room for padding
cipher.resize(plain.size()+AES::BLOCKSIZE);
ArraySink cs(&cipher[0], cipher.size());
ArraySource(plain.data(), plain.size(), true,
new StreamTransformationFilter(enc, new Redirector(cs)));
// Set cipher text length now that its known
cipher.resize(cs.TotalPutLength());
char returnValue[cipher.size()];
copy(cipher.begin(), cipher.end(), returnValue);
return returnValue;
}
Decyption Block:
char* cspl_crypto::decrypt_rijndael(byte key[], byte iv[], int keysize, char
cipher[], int size ){
std::vector<byte> v(cipher, cipher + size);
vector<byte> recover;
CBC_Mode<AES>::Decryption dec;
dec.SetKeyWithIV(key, keysize, iv, keysize);
// Recovered text will be less than cipher text
recover.resize(v.size());
ArraySink rs(&recover[0], recover.size());
ArraySource(v.data(), v.size(), true,
new StreamTransformationFilter(dec, new Redirector(rs)));
// Set recovered text length now that its known
recover.resize(rs.TotalPutLength());
char returnValue[recover.size()];
copy(recover.begin(), recover.end(), returnValue);
return returnValue;
}
Library:
string cspl_crypto::readFile(){
string line;
string returnValue = "";
ifstream myfile ("N07.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
returnValue += line + '\n';
}
myfile.close();
}
else returnValue = "Unable to open file";
return returnValue;
}
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;
}
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];
I need to add AES encryption functionality to my C++ project. So far I am trying to write a wrapper class for Code project: C++ Implementation of AES++ which is to have the following functions:
char* Encrypt(string& InputData); //takes plain text and returns encrypted data
char* Decrypt(string& InputData); //takes encrypted data and returns plain text
But when I test my code only the first 32 bytes of the data are encrypted and decrypted.
The final line of the output is:-
This is Encryption Test My name
What is making it miss the rest of the string? What am I missing?
#include "Rijndael.h"
#include <iostream>
#include <string>
using namespace std;
string LenMod(string Input);
char* Encrypt(string& InputData)
{
try
{
InputData = LenMod(InputData);
char* OutputData = (char*)malloc(InputData.size() + 1);
memset(OutputData, 0, sizeof(OutputData));
CRijndael AESEncrypter;
AESEncrypter.MakeKey("HiLCoE School of Computer Science and Technology",CRijndael::sm_chain0, 16 , 16);
AESEncrypter.Encrypt(InputData.c_str(), OutputData, sizeof(InputData), CRijndael::ECB);
return OutputData;
}
catch(exception e)
{
cout<<e.what();
return NULL;
}
}
char* Decrypt(string& Input)
{
try
{
Input = LenMod(Input);
char* Output = (char*)malloc(Input.size() + 1);
memset(Output, 0, sizeof(Output));
CRijndael AESDecrypter;
AESDecrypter.MakeKey("HiLCoE School of Computer Science and Technology",CRijndael::sm_chain0, 16, 16);
AESDecrypter.Decrypt(Input.c_str(), Output, sizeof(Input), CRijndael::ECB);
return Output;
}
catch(exception e)
{
cout<<e.what();
return NULL;
}
}
string LenMod(string Input)
{
while(Input.length() % 16 != 0)
Input += '\0';
return Input;
}
int main()
{
string s = "This is Encryption Test My name is yohannes tamru i am a computer science student";
//cout<<LengthMod(s)<<endl;
string temp1(Encrypt(s));
string temp2(Decrypt(temp1));
cout<<temp1<<endl<<endl<<temp2<<endl;
system("pause");
return 0;
}
I just found an elusive bug in a program and it turned out to be because with optimization enabled, in something like the following sometimes the std::string is destroyed before processDocument() got the text out of it:
#include <stdio.h>
#include <spawn.h>
#include <string>
static void processDocument(const char* text) {
const char* const argv[] = {
"echo",
text,
NULL,
};
pid_t p;
posix_spawnp(&p, "echo", NULL, NULL, (char**) argv, environ);
}
static int mark = 'A';
static void createDocument() {
const char* vc;
std::string v = "ABCKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK42";
++mark;
v[0] = mark;
vc = v.c_str();
processDocument(vc);
}
int main() {
createDocument();
createDocument();
return(0);
}
How do I safely convert a std::string to a char* for use in execvp, posix_spawnp etc ?
I found out why it really was (here the actual minimal testcase):
std::string resultString;
const char* nodeText;
const char* altText;
resultString = "......whatever1.";
nodeText = resultString.c_str();
resultString = ".....whatever2..";
altText = resultString.c_str();
printf("%s\n", nodeText); // garbage
Bad idea.