How to use Crypto++ to perfom DH key exchange (CryptoPP::DH::Agree returns false) - crypto++

I'm trying to use Crypto++ to perform Diffie-Hellman key exchange. I have written a simple program to check if this is working. As you can guess, it is not.
This program was written based on wiki article: https://www.cryptopp.com/wiki/Diffie-Hellman It is generating public and private keys and then uses them to cal function CryptoPP::DH::Agree. It was working when I was using the same pair of keys for both sides like it is on the wiki. This does not have much practical sense though. However, when I trying to use different keys, CryptoPP::DH::Agree returns false.
I suspect that I'm doing something incorrectly but I have no idea what.
#include <crypto++/cryptlib.h>
#include <crypto++/dh.h>
#include <cryptopp/dh2.h>
#include <crypto++/osrng.h>
#include <crypto++/integer.h>
#include <crypto++/nbtheory.h>
#include <iostream>
static CryptoPP::AutoSeededRandomPool rnd;
static CryptoPP::DH dhA, dhB;
static CryptoPP::SecByteBlock privKeyA, pubKeyA, privKeyB, pubKeyB;
static void createDomainParameters(CryptoPP::DH &dh)
{
CryptoPP::PrimeAndGenerator pg;
pg.Generate(1, rnd, 512, 511);
const CryptoPP::Integer p = pg.Prime();
const CryptoPP::Integer q = pg.SubPrime();
const CryptoPP::Integer g = pg.Generator();
std::cout << "P: " << p << '\n';
std::cout << "Q: " << q << '\n';
std::cout << "G: " << g << '\n';
dh = CryptoPP::DH(p, q, g);
}
static void createAsymetricKey(const CryptoPP::DH &dh, CryptoPP::SecByteBlock &privKey, CryptoPP::SecByteBlock &pubKey)
{
privKey = CryptoPP::SecByteBlock(dh.PrivateKeyLength());
pubKey = CryptoPP::SecByteBlock(dh.PublicKeyLength());
dh.GenerateKeyPair(rnd, privKey, pubKey);
CryptoPP::Integer a, b;
a.Decode(privKey.BytePtr(), privKey.SizeInBytes());
std::cout << "privKey: " << a << std::endl;
b.Decode(pubKey.BytePtr(), pubKey.SizeInBytes());
std::cout << "pubKey: " << b << std::endl;
}
static void createSymetricKey(const CryptoPP::DH &dh, const CryptoPP::SecByteBlock &privKey, const CryptoPP::SecByteBlock &pubKey)
{
CryptoPP::SecByteBlock shared(dh.AgreedValueLength());
if(!dh.Agree(shared, privKey, pubKey))
throw std::runtime_error("Failed to reach shared secret");
CryptoPP::Integer x;
x.Decode(shared.BytePtr(), shared.SizeInBytes());
std::cout << "shared: " << x << std::endl;
}
int main()
{
std::cout << std::hex;
createDomainParameters(dhA);
std::cout << std::endl;
createDomainParameters(dhB);
std::cout << "\n------------------------------\n" << std::endl;
createAsymetricKey(dhA, privKeyA, pubKeyA);
std::cout << std::endl;
createAsymetricKey(dhB, privKeyB, pubKeyB);
if(dhA.AgreedValueLength() != dhB.AgreedValueLength())
throw std::runtime_error("Shared secret size mismatch");
std::cout << "\n------------------------------\n" << std::endl;
createSymetricKey(dhA, privKeyA, pubKeyB);
std::cout << std::endl;
createSymetricKey(dhB, privKeyB, pubKeyA);
return 0;
}
When you change calls of createSymetricKey so it uses key from the same pair, it works.
createSymetricKey(dhA, privKeyA, pubKeyA);
std::cout << std::endl;
createSymetricKey(dhB, privKeyB, pubKeyB);
AFAIK this has no sense though. What is the correct way to use CryptoPP::DH::Agree?

Related

I can't type in cin.getline()

I've found an exemplary code where cin.getline() is used:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int a;
char ch[80];
cin >> a;
cin.getline(ch,80);
cout << a << endl;
cout << ch << endl;
return 0;
}
Could anyone explain me why I can't type anything in cin.getline(ch,80) and "a" is printed after typing a value? I know that cin.getline() reads till "\n", but there isn't "\n" anywhere. I'm a bit confused.

DICOM to Point Cloud in VTK

Is there any method for converting DICOM (ct scan) images to Point Clouds using VTK?
VTK allows reading DICOM and DICOM series and volume rendering but is it possible to generate a Point Cloud from a series of DICOM images?
If it isn't possible in VTK, is there some other library that I can use for this purpose?
Here is a dicom to point cloud demonstration. Dicom files are pretty variable depending on how the imaging is collected, but this is what we have been using for CT scans for some time. This is the "manual version" ie where you will need to interact with the terminal to navigate the dicom directory. It is possible to automate this but is highly dependent on your application.
I have pcl 8.0 and vtkdicom installed. (i was able to do a limited implementation of this without vtkdicom, but its features make the application far more robust at handling diverse dicom directory structures).
You will need to point the function in the main towards the appropriate directory on your computer (should be the file containing the DICOMDIR file). Once you have loaded the dicom, the visualizer has keyboard inputs m and n to control intensity target to be visualized. (you can easily change the code to filter for any of the parameters: x,y,z,intensity) and can change the width or stepsize as needed.
#include <pcl/common/common_headers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/passthrough.h>
#include <boost/thread/thread.hpp>
#include <vtkSmartPointer.h>
#include <vtkDICOMImageReader.h>
#include "vtkImageData.h"
#include "vtkDICOMDirectory.h"
#include "vtkDICOMItem.h"
#include "vtkStringArray.h"
#include "vtkIntArray.h"
#include "vtkDICOMReader.h"
bool loadDICOM(pcl::PointCloud<pcl::PointXYZI>::Ptr outCloud, std::string fullPathToDicomDir)
{
// load DICOM dir file
vtkSmartPointer<vtkDICOMDirectory> ddir =
vtkSmartPointer<vtkDICOMDirectory>::New();
ddir->SetDirectoryName(fullPathToDicomDir.c_str());
ddir->Update();
//select patient
int n = ddir->GetNumberOfPatients();
int patientSelection = 0;
if (n > 1)
{
std::cout << "Select Patient number, total count: " << n << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
patientSelection = std::stoi(userInput);
}
const vtkDICOMItem& patientItem = ddir->GetPatientRecord(patientSelection);
std::cout << "Patient " << patientSelection << ": " << patientItem.Get(DC::PatientID).AsString() << "\n";
//select study
vtkIntArray* studies = ddir->GetStudiesForPatient(patientSelection);
vtkIdType m = studies->GetMaxId() + 1;
int studySelection = 0;
if (m > 1)
{
std::cout << "Select study, total count: " << m << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
studySelection = std::stoi(userInput);
}
int j = studies->GetValue(studySelection);
const vtkDICOMItem& studyItem = ddir->GetStudyRecord(j);
const vtkDICOMItem& studyPItem = ddir->GetPatientRecordForStudy(j);
cout << " Study " << j << ": \""
<< studyItem.Get(DC::StudyDescription).AsString() << "\" \""
<< studyPItem.Get(DC::PatientName).AsString() << "\" "
<< studyItem.Get(DC::StudyDate).AsString() << "\n";
int k0 = ddir->GetFirstSeriesForStudy(j);
int k1 = ddir->GetLastSeriesForStudy(j);
int seriesSelection;
std::cout << "Select series, range: " << k0 << " to " << k1 << std::endl;
for (int i = k0; i <= k1; i++)
{
const vtkDICOMItem& seriesItem = ddir->GetSeriesRecord(i);
vtkStringArray* a = ddir->GetFileNamesForSeries(i);
cout << " Series " << i << ": \""
<< seriesItem.Get(DC::SeriesDescription).AsString() << "\" "
<< seriesItem.Get(DC::SeriesNumber).AsString() << " "
<< seriesItem.Get(DC::Modality).AsString() << ", Images: "
<< a->GetNumberOfTuples() << "\n";
}
std::string userInput;
std::getline(std::cin, userInput);
seriesSelection = std::stoi(userInput);
const vtkDICOMItem& seriesItem = ddir->GetSeriesRecord(seriesSelection);
cout << " Series " << seriesSelection << ": \""
<< seriesItem.Get(DC::SeriesDescription).AsString() << "\" "
<< seriesItem.Get(DC::SeriesNumber).AsString() << " "
<< seriesItem.Get(DC::Modality).AsString() << "\n";
vtkStringArray* a = ddir->GetFileNamesForSeries(seriesSelection);
vtkDICOMReader* reader = vtkDICOMReader::New();
reader->SetFileNames(a);
reader->Update();
vtkSmartPointer<vtkImageData> sliceData = reader->GetOutput();
int numberOfDims = sliceData->GetDataDimension();
int* dims = sliceData->GetDimensions();
std::cout << "Cloud dimensions: ";
int totalPoints = 1;
for (int i = 0; i < numberOfDims; i++)
{
std::cout << dims[i] << " , ";
totalPoints = totalPoints * dims[i];
}
std::cout << std::endl;
std::cout << "Number of dicom points: " << totalPoints << std::endl;
//read data into grayCloud
double* dataRange = sliceData->GetScalarRange();
double* spacingData = reader->GetDataSpacing();
std::cout << "Data intensity bounds... min: " << dataRange[0] << ", max: " << dataRange[1] << std::endl;
if (numberOfDims != 3)
{
std::cout << "Incorrect number of dimensions in dicom file, generation failed..." << std::endl;
return false;
}
else
{
Eigen::RowVector3f spacing = Eigen::RowVector3f(spacingData[0], spacingData[1], spacingData[2]);
Eigen::RowVector3i dimensions = Eigen::RowVector3i(dims[0], dims[1], dims[2]);
outCloud->points.clear();
std::cout << "x spacing: " << spacing(0) << std::endl;
std::cout << "y spacing: " << spacing(1) << std::endl;
std::cout << "z spacing: " << spacing(2) << std::endl;
for (int z = 0; z < dims[2]; z++)
{
if (z % 50 == 0)
{
double percentageComplete = (double)z / (double)dims[2];
std::cout << "Dicom Read Progress: " << (int)(100.0 * percentageComplete) << "%" << std::endl;
}
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
double tempIntensity = sliceData->GetScalarComponentAsDouble(x, y, z, 0);
int tempX = x;
pcl::PointXYZI tempPt = pcl::PointXYZI();
if (!isinf(tempIntensity) && !isnan(tempIntensity))
{
//map value into positive realm
//tempIntensity = ((tempIntensity - dataRange[0]) / (dataRange[1] - dataRange[0]));
if (tempIntensity > SHRT_MAX) { tempIntensity = SHRT_MAX; }
else if (tempIntensity < SHRT_MIN) { tempIntensity = SHRT_MIN; }
}
else
{
tempIntensity = 0;
}
tempPt.x = tempX;
tempPt.y = y;
tempPt.z = z;
tempPt.intensity = tempIntensity;
outCloud->points.push_back(tempPt);
}
}
}
}
std::cout << "Load Dicom Cloud Complete!" << std::endl;
return true;
}
int indexSlice = 0;
void keyboardEventOccurred(const pcl::visualization::KeyboardEvent& event, void* viewer)
{
if (event.getKeySym() == "n" && event.keyDown())
{
indexSlice -= 1;
}
else if (event.getKeySym() == "m" && event.keyDown())
{
indexSlice += 1;
}
}
void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, std::string field, int step, int width, std::string window_name = "default")
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
pcl::PointCloud<pcl::PointXYZI>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZI>);
pcl::PassThrough<pcl::PointXYZI> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName(field); //could gate this on intensity if u preferred
int lastIndex = indexSlice-1; //proc first cycle
while (!viewer->wasStopped()) {
if (indexSlice != lastIndex)
{
int low = step * indexSlice - width / 2;
int high = step * indexSlice + width / 2;
pass.setFilterLimits(low, high);
pass.filter(*tempCloud);
lastIndex = indexSlice;
std::cout << field<< " range: " <<low<<" , "<<high<< std::endl;
viewer->removeAllPointClouds();
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(tempCloud, "intensity");
viewer->addPointCloud< pcl::PointXYZI >(tempCloud, point_cloud_color_handler, "id");
}
viewer->spinOnce(50);
}
viewer->close();
}
// --------------
// -----Main-----
// --------------
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
loadDICOM(cloud, "C:/Local Software/voyDICOM/resources/DICOM_Samples/2021APR14 MiniAchors_V0");
displayCloud(cloud,"intensity",100,50);
return 0;
}
Note that in most cases dicom files are relatively massive in terms of raw dimensions and so I very rarely (never?) have loaded a whole dicom file into a point cloud (until for this code). Generally what I do is handle it in a dense format (short array) and then create clouds based on selections from that data. This way you can do certain imaging operations that benefit from a locked data grid (opening, closing, etc) prior to going to the sparse data set (point cloud) where everything becomes profoundly more expensive.
Pretty picture of it working with one of my debug dicom sets:
I think I might have found a way, after all. Haven't tried it yet but in theory it should work.
Firstly, the DICOM image needs to be converted into .vtk format using VTK once the DICOM images have been converted into .vtk they can then be converted into .pcd (Point cloud format) using PCL (point cloud library).

The result of opencv3.3 dnn module not match the caffe prediction

I used opencv dnn classification, but the result do not match the caffe prediction. What confused me was that some images could get similar result to caffe,a small number of images not.When I changed BGR to RGB, Most of the results ware wrong.
similar result:
different result:
blobFromImage(norm_img, 1.0, cv::Size(64, 64));when used default parameters changed BGR to RGB ,but the result would wrong .so I used like this blobFromImage(norm_img, 1.0, cv::Size(64, 64), cv::Scalar(),false); .most of result would matched caffe prediction,why a small number of images not?
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/trace.hpp>
using namespace cv;
using namespace cv::dnn;
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace std;
/* Find best class for the blob (i. e. class with maximal probability) */
static void getMaxClass(const Mat &probBlob, int *classId, double *classProb)
{
Mat probMat = probBlob.reshape(1, 1); //reshape the blob to 1x1000 matrix
Point classNumber;
minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
*classId = classNumber.x;
}
static std::vector<String> readClassNames(const char *filename = "./config/type.txt")
{
std::vector<String> classNames;
std::ifstream fp(filename);
if (!fp.is_open())
{
std::cerr << "File with classes labels not found: " << filename << std::endl;
exit(-1);
}
std::string name;
while (!fp.eof())
{
std::getline(fp, name);
if (name.length())
classNames.push_back(name.substr(name.find(' ') + 1));
}
fp.close();
return classNames;
}
int main(int argc, char **argv)
{
CV_TRACE_FUNCTION();
String modelTxt = "./config/HCCR3755_res20_deploy.prototxt";
String modelBin = "./config/HCCR3755-res20_iter_790000.caffemodel";
String imageFile = "./config/b9.jpg";
Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
if (net.empty())
{
std::cerr << "Can't load network by using the following files: " << std::endl;
std::cerr << "prototxt: " << modelTxt << std::endl;
std::cerr << "caffemodel: " << modelBin << std::endl;
exit(-1);
}
Mat img = imread(imageFile);
FileStorage fs("./config/mean.xml", FileStorage::READ);
Mat _mean;
fs["vocabulary"] >> _mean;
if (img.empty())
{
std::cerr << "Can't read image from the file: " << imageFile << std::endl;
exit(-1);
}
cv::Mat img_resize;
resize(img, img_resize, Size(64, 64));
cv::Mat img_float;
img_resize.convertTo(img_float, CV_32FC3);
cv::Mat norm_img;
cv::subtract(img_float, _mean, norm_img);
Mat inputBlob = blobFromImage(norm_img, 1.0, cv::Size(64, 64), cv::Scalar(),false); //Convert Mat to batch of images
Mat prob;
cv::TickMeter t;
for (int i = 0; i < 1; i++)
{
CV_TRACE_REGION("forward");
//! [Set input blob]
net.setInput(inputBlob, "data"); //set the network input
//! [Set input blob]
t.start();
//! [Make forward pass]
prob = net.forward("prob");
//std::cout << prob << std::endl;//compute output
//! [Make forward pass]
t.stop();
}
int classId;
double classProb;
getMaxClass(prob, &classId, &classProb);//find the best class
//! [Gather output]
//! [Print results]
std::vector<String> classNames = readClassNames();
std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
std::cout << "Probability: " << classProb * 100 << "%" << std::endl;
//! [Print results]
std::cout << "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " << t.getCounter() << " iterations)" << std::endl;
getchar();
return 0;
} //main

AES128 encrypt/decrypt using gcrypt in c++

i couldnt find a working good example so ive created one
you can change mykey ,and make the iv random using one of the gcrypt function.
sample
#include <iostream>
#include <gcrypt.h>
typedef unsigned char byte;
using namespace std;
#define BLOCK 16
const byte mykey []= {0x2d,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72};
const byte end1[] ={0x0};
const byte message [] = {0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72,0x20,0x61,0x6C,0x6C,0x20,0x67,0x6F,0x6F,0x64,0x20,0x6D,0x65,0x6E,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6D,0x65,0x20,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x61,0x69,0x64,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x75,0x6E,0x74,0x72,0x79,0x2E,0x00 };
const byte end[] = {0x00};
// encrypt
// Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
// block in place.
#define roundup(x,n) \
n *((sizeof(x))/n + (((sizeof(x))%n)+1)/(((sizeof(x))%n)+1))
void verify ( gcry_error_t err, const char* msg ) {
if (err) {
cout << msg << " " << gcry_strsource(err)<< " / " << gcry_strerror(err) << endl;
exit(1);
}
}
/* PROGMA BEGIN
* encrypt decrypt
* using the GCRYPT */
int main (){
gcry_error_t err = 0;
// init the lib ..
if (!gcry_check_version (GCRYPT_VERSION))
{ cout << "gcrypt: library version mismatch" << endl; exit(1); }
err = gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
err |= gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
verify (err,"gcrypt: failed initialization");
//init the operation mode
#define GCRY_CIPHER GCRY_CIPHER_AES128
#define GCRY_MODE GCRY_CIPHER_MODE_ECB
//#define GCRY_FLAG GCRY_CIPHER_ENABLE_SYNC
#define GCRY_FLAG 0
gcry_cipher_hd_t handle;
err = gcry_cipher_open( &handle, GCRY_CIPHER, GCRY_MODE, GCRY_FLAG);
verify ( err, "gcry_cipher_open" ) ;
byte iv[BLOCK];
memset(iv,0x23,BLOCK); // just for example, we should get it from the cipher word, first 16 bytes
memset(iv, 0x89 , BLOCK -4);
err = gcry_cipher_setiv(handle,iv,BLOCK);
verify( err, "set iv ");
cout <<"iv seT: "<< BLOCK << ":"<< iv << endl;
err = gcry_cipher_setkey(handle, mykey, sizeof(mykey));
verify( err, "set KeY ");
cout << "KeY set: "<< sizeof(mykey) <<":";// << mykey << endl;
for ( int i = 0 ; i <sizeof(mykey) ; ++i ) cout << mykey[i];
cout << endl;
// init done
// in = message
// out - new
unsigned char out[ roundup(message,BLOCK) ];
memset(out,0,roundup(message,BLOCK) );
//memcpy( out, message, sizeof(message));
size_t outsize = sizeof(out);
err = gcry_cipher_encrypt( handle, out, outsize, message, outsize);
verify( err, "encrypt " );
cout <<endl<< "encrypt in: " << sizeof(message) << ":" << message << endl ;
cout << "encrypt out: " << outsize << ":"<< out << endl<<endl;
unsigned char decrypt[roundup(out,BLOCK)]; // to out
memset(decrypt, 0 , roundup(out,BLOCK) );
size_t dsize= sizeof(decrypt);
err = gcry_cipher_decrypt( handle, decrypt, dsize, out, outsize);
verify( err, "decrypt " );
cout << "decrypt in: " << outsize << ":";
for ( int i = 0 ; i < outsize ; ++i ) cout << out[i];
cout << endl;
cout << "decrypt out: " << dsize << ":"<< decrypt << endl;
gcry_cipher_close(handle);
return 0;
}
/* g++ -std=c++11 xxx.cpp -L/usr/lib64 -lgcrypt -lgpg-error*/
any comment is welcome
i know it doesn't look that good , tried to be concised

How to use remove_if with vector<point2f>

I have a vector that has lots of NaN's for x,y positions that I want to remove(doing some opencv work). I cannot figure out how to use remove_if to remove the NaNs(when used in conjunction with erase). I've seen lots of examples if the vector is float or int but not point2f. Any simple examples would be very helpful. Thanks.
You can use a lambda function, or a functor or a function pointer. This is an example with a lambda function:
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace cv;
using namespace std;
int main(int argc, char ** argv)
{
vector<Point2f> pts{ Point2f(1.f, 2.f), Point2f(3.f, sqrt(-1.0f)), Point2f(2.f, 3.f) };
cout << "Before" << endl;
for (const auto& p : pts) {
cout << p << " ";
}
cout << endl;
pts.erase(remove_if(pts.begin(), pts.end(), [](const Point2f& p)
{
// Check if a coordinate is NaN
return isnan(p.x) || isnan(p.y);
}), pts.end());
cout << "After" << endl;
for (const auto& p : pts) {
cout << p << " ";
}
cout << endl;
return 0;
}
That will print:
Before
[1, 2] [3, -1.#IND] [2, 3]
After
[1, 2] [2, 3]

Resources