diff --git a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp index 3c7e6ad..2a4fd76 100644 --- a/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp +++ b/lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp @@ -82,7 +82,9 @@ constexpr uint16_t toSW(byte_type sw1, byte_type sw2) noexcept } /** Convert bytes to hex string. */ -std::string bytes2hexstr(const byte_vector& bytes); +std::ostream& operator<<(std::ostream& os, const pcsc_cpp::byte_vector& data); + +std::string operator+(std::string lhs, const byte_vector& rhs); /** Struct that wraps response APDUs. */ struct ResponseApdu @@ -129,7 +131,7 @@ struct ResponseApdu friend std::string operator+(std::string&& lhs, const ResponseApdu& rhs) { - return lhs + pcsc_cpp::bytes2hexstr(rhs.data) + pcsc_cpp::bytes2hexstr({rhs.sw1, rhs.sw2}); + return lhs + rhs.data + byte_vector {rhs.sw1, rhs.sw2}; } }; diff --git a/lib/libpcsc-cpp/src/utils.cpp b/lib/libpcsc-cpp/src/utils.cpp index ce171f6..82703e5 100644 --- a/lib/libpcsc-cpp/src/utils.cpp +++ b/lib/libpcsc-cpp/src/utils.cpp @@ -36,11 +36,11 @@ using namespace std::string_literals; #undef LOBYTE #endif -constexpr byte_type HIBYTE(size_t w) +constexpr byte_type HIBYTE(size_t w) noexcept { return static_cast((w >> 8) & 0xff); } -constexpr byte_type LOBYTE(size_t w) +constexpr byte_type LOBYTE(size_t w) noexcept { return static_cast(w & 0xff); } @@ -57,10 +57,9 @@ class UnexpectedResponseError : public Error explicit UnexpectedResponseError(const CommandApdu& command, const ResponseApdu& response, const char* file, const int line, const char* callerFunctionName) : - Error("transmitApduWithExpectedResponse(): Unexpected response to command '"s - + bytes2hexstr(command) + "' - expected '9000', got '"s + response + "' in " - + removeAbsolutePathPrefix(file) + ':' + std::to_string(line) + ':' - + callerFunctionName) + Error("transmitApduWithExpectedResponse(): Unexpected response to command '"s + command + + "' - expected '9000', got '"s + response + "' in " + removeAbsolutePathPrefix(file) + + ':' + std::to_string(line) + ':' + callerFunctionName) { } }; @@ -70,15 +69,19 @@ class UnexpectedResponseError : public Error namespace pcsc_cpp { -std::string bytes2hexstr(const byte_vector& bytes) +std::ostream& operator<<(std::ostream& os, const pcsc_cpp::byte_vector& data) { - std::ostringstream hexStringBuilder; - - hexStringBuilder << std::setfill('0') << std::hex; - - for (const auto byte : bytes) - hexStringBuilder << std::setw(2) << short(byte); + os << std::setfill('0') << std::hex; + for (const auto byte : data) + os << std::setw(2) << short(byte); + return os; +} +std::string operator+(std::string lhs, const byte_vector& rhs) +{ + lhs.reserve(lhs.size() + rhs.size() * 2); + std::ostringstream hexStringBuilder(std::move(lhs)); + hexStringBuilder << rhs; return hexStringBuilder.str(); } @@ -103,8 +106,8 @@ size_t readDataLengthFromAsn1(const SmartCard& card) if (response.data[0] != DER_SEQUENCE_TYPE_TAG) { // TODO: more specific exception THROW(Error, - "readDataLengthFromAsn1(): First byte must be SEQUENCE (0x30), but is 0x"s - + bytes2hexstr({response.data[0]})); + "readDataLengthFromAsn1(): First byte must be SEQUENCE (0x30), but is "s + + int2hexstr(response.data[0])); } // TODO: support other lenghts besides 2. @@ -113,8 +116,8 @@ size_t readDataLengthFromAsn1(const SmartCard& card) // TODO: more specific exception THROW(Error, "readDataLengthFromAsn1(): Second byte must be two-byte length indicator "s - "(0x82), but is 0x"s - + bytes2hexstr({response.data[1]})); + "(0x82), but is "s + + int2hexstr(response.data[1])); } // Read 2-byte length field at offset 2 and 3 and add the 4 DER length bytes. diff --git a/src/electronic-id.cpp b/src/electronic-id.cpp index f840d1c..e152989 100644 --- a/src/electronic-id.cpp +++ b/src/electronic-id.cpp @@ -213,19 +213,6 @@ const std::vector MASKED_ATRS = { constructor}, }; -std::string byteVectorToHexString(const byte_vector& bytes) -{ - std::ostringstream hexStringBuilder; - - hexStringBuilder << std::setfill('0') << std::hex; - - for (const auto byte : bytes) { - hexStringBuilder << std::setw(2) << static_cast(byte); - } - - return hexStringBuilder.str(); -} - const auto SUPPORTED_ALGORITHMS = std::map { {"SHA-224"s, HashAlgorithm::SHA224}, {"SHA-256"s, HashAlgorithm::SHA256}, {"SHA-384"s, HashAlgorithm::SHA384}, {"SHA-512"s, HashAlgorithm::SHA512}, @@ -270,8 +257,7 @@ ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader) // It should be verified that the card is supported with isCardSupported() before // calling getElectronicID(), so it is a programming error to reach this point. - THROW(ProgrammingError, - "Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported"); + THROW(ProgrammingError, "Card with ATR '" + reader.cardAtr + "' is not supported"); } bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo) const diff --git a/tests/common/selectcard.hpp b/tests/common/selectcard.hpp index 05e1580..171af07 100644 --- a/tests/common/selectcard.hpp +++ b/tests/common/selectcard.hpp @@ -14,8 +14,3 @@ inline electronic_id::CardInfo::ptr autoSelectSupportedCard() { return cardList[0]; } - -inline std::ostream &operator<<(std::ostream &os, const pcsc_cpp::byte_vector &data) -{ - return os << pcsc_cpp::bytes2hexstr(data); -} diff --git a/tests/integration/test-get-certificate.cpp b/tests/integration/test-get-certificate.cpp index 1a0e872..8de61a0 100644 --- a/tests/integration/test-get-certificate.cpp +++ b/tests/integration/test-get-certificate.cpp @@ -26,6 +26,8 @@ #include +using namespace pcsc_cpp; + TEST(electronic_id_test, getCertificate) { using namespace electronic_id;