This library provides a simple and nice C++ wrapper around these libraries, so that programmers can concentrate on functionality. It offers general support for PCSC-lite, OpenSSL, PKCS#11, plus specific functionality for the SuisseID.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
5.3 KiB
133 lines
5.3 KiB
11 years ago
|
/*! @file
|
||
|
|
||
|
@id $Id$
|
||
|
*/
|
||
|
// 1 2 3 4 5 6 7 8
|
||
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||
|
|
||
|
#include <string>
|
||
|
#include <map>
|
||
|
#include <iostream>
|
||
|
#include <iomanip>
|
||
|
#include <algorithm>
|
||
|
#include <tuple>
|
||
|
#include <sstream>
|
||
|
#include <fstream>
|
||
|
#include <streambuf>
|
||
|
#include <chrono>
|
||
|
#include <cryptoki.hxx>
|
||
|
|
||
|
unsigned long r(1);
|
||
|
std::string txt("This is an example.");
|
||
|
std::string lib("libcvP11.so");
|
||
|
std::string slot;
|
||
|
std::string cert;
|
||
|
|
||
|
typedef std::map<std::string,
|
||
|
std::tuple<std::string*, unsigned long*, std::string*, std::string> >
|
||
|
Args;
|
||
|
Args args = {
|
||
|
// option 2 3 4 description
|
||
|
{"-h", Args::mapped_type(0, 0, 0, "same as --help")},
|
||
|
{"--help", Args::mapped_type(0, 0, 0, "show help")},
|
||
|
{"-r", Args::mapped_type(0, &r, 0, "same as --repeat")},
|
||
|
{"--repeat", Args::mapped_type(0, &r, 0, "<number> of repetitions")},
|
||
|
{"-t", Args::mapped_type(0, 0, &txt, "same as --text")},
|
||
|
{"--text", Args::mapped_type(0, 0, &txt, "<file> with text to sign")},
|
||
|
{"-l", Args::mapped_type(&lib, 0, 0, "same as --library")},
|
||
|
{"--library", Args::mapped_type(&lib, 0, 0, "<library> cryptoki to load")},
|
||
|
{"-s", Args::mapped_type(&slot, 0, 0, "same as --slot")},
|
||
|
{"--slot", Args::mapped_type(&slot, 0, 0, "<name> of slot")},
|
||
|
{"-c", Args::mapped_type(&cert, 0, 0, "same as --certificae")},
|
||
|
{"--certificate", Args::mapped_type(&cert, 0, 0, "<cert> name to use")}
|
||
|
// 2: read string from command line
|
||
|
// 3: read unsigned long integer from command line
|
||
|
// 4: read string from file given on command line
|
||
|
};
|
||
|
|
||
|
int main(int argc, char** argv) try {
|
||
|
for (auto arg(argv+1); arg<argv+argc; ++arg) {
|
||
|
auto it(args.find(*arg));
|
||
|
if (it!=args.end() &&
|
||
|
(std::get<0>(it->second)!=0 || std::get<1>(it->second)!=0 ||
|
||
|
std::get<2>(it->second)!=0)
|
||
|
&& arg+1<argv+argc) {
|
||
|
if (std::get<0>(it->second)) {
|
||
|
*std::get<0>(it->second) = *++arg;
|
||
|
} else if (std::get<1>(it->second)) {
|
||
|
((std::stringstream&)(std::stringstream()<<*++arg))
|
||
|
>>*std::get<1>(it->second);
|
||
|
} else if (std::get<2>(it->second)) {
|
||
|
std::ifstream t(*++arg);
|
||
|
*std::get<2>(it->second) = std::string
|
||
|
(std::istreambuf_iterator<char>(t),
|
||
|
std::istreambuf_iterator<char>());
|
||
|
}
|
||
|
} else { // argument type 0 or wrong parameter displays help
|
||
|
std::cerr<<"SYNOPSIS"<<std::endl;
|
||
|
std::cerr<<" "<<argv[0]<<" [OPTIONS]"<<std::endl;
|
||
|
std::cerr<<"DESCRIPTION"<<std::endl;
|
||
|
std::cerr<<" sign a text, optionally multiple times for"<<std::endl;
|
||
|
std::cerr<<" performance tests"<<std::endl;
|
||
|
std::cerr<<"OPTIONS"<<std::endl;
|
||
|
std::for_each(args.begin(), args.end(), [](Args::value_type v){
|
||
|
std::cerr<<" "<<std::setw(10)<<std::setfill(' ')
|
||
|
<<v.first<<' '<<std::get<3>(v.second)
|
||
|
<<std::endl;
|
||
|
});
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
std::cout<<"Sign text "<<r<<" times:"<<std::endl
|
||
|
<<"-----------------------------------------------------"<<std::endl
|
||
|
<<txt<<std::endl
|
||
|
<<"-----------------------------------------------------"<<std::endl;
|
||
|
cryptoki::Init c(lib);
|
||
|
cryptoki::SlotList s(c.slotList());
|
||
|
std::for_each(s.begin(), s.end(), [](cryptoki::Slot s){
|
||
|
cryptoki::SlotInfo si(s.slotinfo());
|
||
|
if (slot.size()&&slot!=si.slotDescription) return;
|
||
|
std::cout<<"Found Slot: "<<si.slotDescription<<std::endl;
|
||
|
cryptoki::TokenInfo ti(s.tokeninfo());
|
||
|
std::cout<<"Found token: "<<ti.label<<std::endl;
|
||
|
cryptoki::Session session(s);
|
||
|
cryptoki::ObjectList certs
|
||
|
(session.find(cryptoki::Attribute(CKA_CLASS)
|
||
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
|
||
|
std::for_each(certs.begin(), certs.end(), [&session](cryptoki::Object c){
|
||
|
std::string label(c.attribute(CKA_LABEL).value);
|
||
|
if (cert.size()&&cert!=label) return;
|
||
|
cryptoki::Attribute id(c.attribute(CKA_ID));
|
||
|
cryptoki::ObjectList keys
|
||
|
(session.find(cryptoki::Attribute(CKA_CLASS)
|
||
|
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY),
|
||
|
id));
|
||
|
if (!keys.size()) return;
|
||
|
std::cout<<"Found Certificate: "
|
||
|
<<c.attribute(CKA_LABEL).value<<std::endl;
|
||
|
std::cout<<"Pin: ";
|
||
|
std::string pin;
|
||
|
std::cin>>pin;
|
||
|
cryptoki::Session::Login l(session, pin);
|
||
|
keys = session.find(cryptoki::Attribute(CKA_CLASS)
|
||
|
.from<CK_OBJECT_CLASS>(CKO_PRIVATE_KEY),
|
||
|
id);
|
||
|
if (keys.size()!=1) {
|
||
|
std::cerr<<"**** ERROR: No private key: "<<keys.size()<<std::endl;
|
||
|
return;
|
||
|
}
|
||
|
std::cout<<"Signing ..."<<std::endl;
|
||
|
auto start = std::chrono::system_clock::now();
|
||
|
for (int i(0); i<r; ++i)
|
||
|
keys[0].sign(txt, CKM_RSA_PKCS);
|
||
|
auto end = std::chrono::system_clock::now();
|
||
|
auto elapsed =std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||
|
std::cout<<"Done in "<<elapsed.count()<<"ms"<<std::endl;
|
||
|
});
|
||
|
});
|
||
|
return 0;
|
||
|
} catch (std::exception& x) {
|
||
|
std::cerr<<"**** ERROR: "<<x.what()<<std::endl;
|
||
|
return 1;
|
||
|
}
|