/*! @file
@ id $ Id $
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
# ifndef __CRYPTAUX_HXX__
# define __CRYPTAUX_HXX__
# include <string>
# include <sstream>
# include <iomanip>
# include <stdexcept>
# include <algorithm>
/*! @defgroup gcrypto Auxiliary Crypto-Functions
Auxiliary often used funcions in cryptographic environment , such
as logging , converting binary from and to hexadecimal or creating
readable texts from binary data . */
//@{
# define CRYPTOLOG_QUOTE(X) CRYPTOLOG_QUOTE2(X)
# define CRYPTOLOG_QUOTE2(X) #X
# if __GNUC__ >= 2
# define CRYPTOLOG_END " -- "<<__PRETTY_FUNCTION__<<std::endl
# else
# define CRYPTOLOG_END std::endl
# endif
// Logging, enable with -DDEBUG
# ifndef CRYPTOLOG
# ifndef DEBUG
# define CRYPTOLOG(X)
# else
# include <iostream>
# define CRYPTOLOG(X) { \
std : : string __C_FILE__ ( __FILE__ ) ; \
std : : string __C_LINE__ ( CRYPTOLOG_QUOTE ( __LINE__ ) ) ; \
std : : string : : size_type __LOC_POS__ ( __C_FILE__ . rfind ( ' / ' ) ) ; \
if ( __LOC_POS__ ! = std : : string : : npos ) \
__C_FILE__ = __C_FILE__ . substr ( __LOC_POS__ + 1 ) ; \
std : : string __LOC_SPC1__ ( 18 > __C_FILE__ . size ( ) \
? std : : string ( 18 - __C_FILE__ . size ( ) , ' ' ) \
: std : : string ( ) ) ; \
std : : string __LOC_SPC2__ ( 4 > __C_LINE__ . size ( ) \
? std : : string ( 4 - __C_LINE__ . size ( ) , ' ' ) \
: std : : string ( ) ) ; \
std : : clog < < " CRYPTO: " < < __LOC_SPC1__ < < __C_FILE__ \
< < ' : ' < < __LOC_SPC2__ < < __C_LINE__ < < " -- " < < X \
< < CRYPTOLOG_END ; \
}
# endif
# endif
// Verbose logging, use with care, will also log PINs.
// Enable with -DDEBUG -DVERBOSE
# ifndef CRYPTOLOG_VERBOSE
# if !(defined(DEBUG)&&defined(VERBOSE))
# define CRYPTOLOG_VERBOSE(X)
# else
# include <iostream>
# define CRYPTOLOG_VERBOSE(X) { \
std : : string __C_FILE__ ( __FILE__ ) ; \
std : : string __C_LINE__ ( CRYPTOLOG_QUOTE ( __LINE__ ) ) ; \
std : : string : : size_type __LOC_POS__ ( __C_FILE__ . rfind ( ' / ' ) ) ; \
if ( __LOC_POS__ ! = std : : string : : npos ) \
__C_FILE__ = __C_FILE__ . substr ( __LOC_POS__ + 1 ) ; \
std : : string __LOC_SPC1__ ( 18 > __C_FILE__ . size ( ) \
? std : : string ( 18 - __C_FILE__ . size ( ) , ' ' ) \
: std : : string ( ) ) ; \
std : : string __LOC_SPC2__ ( 4 > __C_LINE__ . size ( ) \
? std : : string ( 4 - __C_LINE__ . size ( ) , ' ' ) \
: std : : string ( ) ) ; \
std : : clog < < " CRYPTO: " < < __LOC_SPC1__ < < __C_FILE__ < < ' : ' \
< < __LOC_SPC2__ < < __C_LINE__ < < " -- " < < X \
< < CRYPTOLOG_END ; \
}
# endif
# endif
namespace pcsc {
/// Get library version identification
std : : string version ( ) ;
}
//! @ref gcrypto @copydoc gcrypto
namespace crypto {
static const std : : string LETTER_CHARS
( " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " ) ;
static const std : : string NUMBER_CHARS
( " 0123456789 " ) ;
//! Contains @c @ in addition to standard characters.
static const std : : string GRAFIC_CHARS
( " ! \" #%&'()*+,-./:;<=>?[ \\ ]^_{|}~@ " ) ;
static const std : : string BLANK_CHARS
( " " ) ;
static const std : : string VALID_CHARS
( LETTER_CHARS + NUMBER_CHARS + GRAFIC_CHARS + BLANK_CHARS ) ;
inline std : : string hex ( const std : : string & data ) {
std : : stringstream res ;
for ( std : : string : : const_iterator it ( data . begin ( ) ) ; it ! = data . end ( ) ; + + it )
res < < std : : hex < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 )
< < ( unsigned int ) ( unsigned char ) * it ;
return res . str ( ) ;
}
inline std : : string hexTxt ( const std : : string & data ,
std : : string : : size_type len = 20 ,
std : : string : : size_type indent = 0 ) {
std : : stringstream res ;
std : : string : : size_type pos ( 0 ) ;
for ( std : : string : : const_iterator it ( data . begin ( ) ) ; it ! = data . end ( ) ; + + it ) {
if ( pos % len = = 0 ) res < < std : : string ( indent , ' ' ) ;
res < < std : : hex < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 )
< < ( unsigned int ) ( unsigned char ) * it ;
+ + pos ;
if ( pos % len = = 0 | | pos = = data . size ( ) ) {
res < < std : : string ( 2 * ( len - ( pos - 1 ) % len ) , ' ' ) ;
for ( std : : string : : size_type i ( pos - ( pos - 1 ) % len - 1 ) ; i < pos ; + + i )
res < < ( VALID_CHARS . find ( data [ i ] ) = = std : : string : : npos ? ' . ' : data [ i ] ) ;
if ( pos ! = data . size ( ) ) res < < std : : endl ;
}
}
return res . str ( ) ;
}
inline std : : string readable ( const std : : string & data ,
std : : string : : size_type len = 20 ,
std : : string : : size_type indent = 0 ) {
if ( ! data . size ( ) )
return std : : string ( indent , ' ' ) + " <empty> " ;
else if ( data . find_first_not_of ( VALID_CHARS ) < data . size ( ) )
return hexTxt ( data , len , indent ) ;
else
return std : : string ( indent , ' ' ) + " \" " + data + " \" " ;
}
//! Convert binary to readable hexadecimal
inline std : : string binToHex ( char c ) {
std : : stringstream ss ;
ss < < std : : hex < < std : : setw ( 2 ) < < std : : setfill ( ' 0 ' )
< < ( unsigned int ) ( unsigned char ) ( c ) ;
return ss . str ( ) ;
}
//! Convert binary to readable hexadecimal
inline std : : string binToHex ( const std : : string & s ) {
std : : string result ;
for ( std : : string : : const_iterator c ( s . begin ( ) ) ; c ! = s . end ( ) ; + + c )
result + = binToHex ( * c ) ;
return result ;
}
//! Convert readable lowercase hexadecimal to binary
inline std : : string hexToBin ( std : : string s ) {
const static std : : string HEX ( " 0123456789abcdef " ) ;
std : : transform ( s . begin ( ) , s . end ( ) , s . begin ( ) , : : tolower ) ;
if ( s . size ( ) % 2 )
throw std : : runtime_error
( " input string \" " + s
+ " \" must have an even number of hexadecimal numbers " ) ;
if ( s . find_first_not_of ( HEX ) ! = std : : string : : npos )
throw std : : runtime_error
( " input string \" " + s + " \" has non hexadecimal value at position "
+ ( ( std : : stringstream & ) ( std : : stringstream ( )
< < s . find_first_not_of ( HEX ) ) ) . str ( ) ) ;
std : : string res ;
for ( std : : string : : const_iterator it ( s . begin ( ) ) ; it ! = s . end ( ) ; + + it ) {
std : : string : : size_type c ( HEX . find ( * it ) ) ;
if ( + + it ! = s . end ( ) ) ( c < < = 4 ) + = HEX . find ( * it ) ;
res + = std : : string ( 1 , ( std : : string : : value_type ) c ) ;
}
return res ;
}
/// convert integer to binary of given size
inline std : : string toBinary ( unsigned long data , int bytes = 2 ) {
std : : string res ( bytes , ' \0 ' ) ;
for ( int i ( 0 ) ; i < bytes ; + + i ) {
res [ i ] = std : : string : : value_type ( data & 0xff ) ;
data > > = 8 ;
}
return res ;
}
/// convert integer from binary of given size
inline unsigned long ulongFromBinary ( const std : : string & data ) {
unsigned long res ( 0 ) ;
for ( std : : string : : const_iterator it ( data . begin ( ) ) ; it ! = data . end ( ) ; + + it )
( res < < = 8 ) + = ( unsigned long ) ( unsigned char ) * it ;
return res ;
}
}
//@}
# endif