--- a/src/lib/ASN1ContentHandler.h Wed Jun 30 20:11:39 2021 +0200
+++ b/src/lib/ASN1ContentHandler.h Fri Jul 02 00:42:01 2021 +0200
@@ -37,19 +37,18 @@
};
enum class StringType : uint64_t {
- OctetString,
- UTF8String,
- NumericString,
- PrintableString,
- T61String,
- VideotexString,
- IA5String,
- GraphicString,
- VisibleString,
- GeneralString,
- UniversalString,
- CharacterString,
- BMPString,
+ UTF8String = 0xC,
+ NumericString = 0x12,
+ PrintableString = 0x13,
+ T61String = 0x14,
+ VideotexString = 0x15,
+ IA5String = 0x16,
+ GraphicString = 0x19,
+ VisibleString = 0x1A,
+ GeneralString = 0x1B,
+ UniversalString = 0x1C,
+ CharacterString = 0x1D,
+ BMPString = 0x1E,
};
enum class DateTimeType : uint64_t {
@@ -238,7 +237,19 @@
virtual void writeBoolean(bool value) = 0;
virtual void writeNull() = 0;
virtual void writeInteger(Integer value) = 0;
- virtual void writeString(StringType type, std::string value) = 0;
+ /**
+ * @param type original type in ASN.1
+ * @param value original text converted to UTF-8
+ */
+ virtual void writeTextString(StringType type, std::string value) = 0;
+ /**
+ * @param value arbitrary sequence of octets (bytes), usually not a human-readable text
+ */
+ virtual void writeOctetString(std::string value) = 0;
+ /**
+ * @param value arbitrary sequence of bits (booleans), usually not a human-readable text
+ */
+ virtual void writeBitString(std::vector<bool> value) = 0;
virtual void writeOID(ObjectIdentifier value) = 0;
virtual void writeDateTime(DateTimeType type, DateTime value) = 0;
// Object descriptor
@@ -290,8 +301,16 @@
handler->writeInteger(value);
}
- void writeString(StringType type, std::string value) override {
- handler->writeString(type, value);
+ void writeTextString(StringType type, std::string value) override {
+ handler->writeTextString(type, value);
+ }
+
+ void writeOctetString(std::string value) override {
+ handler->writeOctetString(value);
+ }
+
+ void writeBitString(std::vector<bool> value) override {
+ handler->writeBitString(value);
}
void writeOID(ObjectIdentifier value) override {
--- a/src/lib/BasicASN1Reader.h Wed Jun 30 20:11:39 2021 +0200
+++ b/src/lib/BasicASN1Reader.h Fri Jul 02 00:42:01 2021 +0200
@@ -207,16 +207,36 @@
std::string s;
s.resize(typeHeader.length);
read((uint8_t*) s.data(), typeHeader.length);
- handlers.writeString(ASN1ContentHandler::StringType::UTF8String, s);
+ handlers.writeTextString(ASN1ContentHandler::StringType::UTF8String, s);
} else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
// TODO: check encoding
// TODO: check available bytes before allocating buffer
std::string s;
s.resize(typeHeader.length);
read((uint8_t*) s.data(), typeHeader.length);
- handlers.writeString(ASN1ContentHandler::StringType::PrintableString, s);
+ handlers.writeTextString(ASN1ContentHandler::StringType::PrintableString, s);
+ } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
+ // TODO: check available bytes before allocating buffer
+ std::string s;
+ s.resize(typeHeader.length);
+ read((uint8_t*) s.data(), typeHeader.length);
+ handlers.writeOctetString(s);
+ } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
+ // TODO: check available bytes before allocating buffer
+ std::string s;
+ s.resize(typeHeader.length);
+ read((uint8_t*) s.data(), typeHeader.length);
+ std::vector<bool> bits;
+ // TODO: throw exception on wrong padding or insufficient length?
+ if (s.size() > 1) {
+ uint8_t padding = s[0];
+ for (uint8_t j = padding; j < 8; j++) bits.push_back(s.back() & 1 << j);
+ for (size_t i = s.size() - 2; i > 0; i--) for (uint8_t j = 0; j < 8; j++) bits.push_back(s[i] & 1 << j);
+ }
+ handlers.writeBitString(bits);
} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
// TODO: check available bytes before allocating buffer
+ // TODO: check encoding
std::string s;
s.resize(typeHeader.length);
read((uint8_t*) s.data(), typeHeader.length);
@@ -295,7 +315,7 @@
<< " length = " << typeHeader.length
<< " definite = " << (typeHeader.definiteLength ? "true" : "false");
- handlers.writeString(ASN1ContentHandler::StringType::UTF8String, description.str());
+ handlers.writeTextString(ASN1ContentHandler::StringType::UTF8String, description.str());
}
commit();
--- a/src/lib/GenericASN1ContentHandler.h Wed Jun 30 20:11:39 2021 +0200
+++ b/src/lib/GenericASN1ContentHandler.h Fri Jul 02 00:42:01 2021 +0200
@@ -16,6 +16,9 @@
*/
#pragma once
+#include <sstream>
+#include <iomanip>
+
#include "ASN1ContentHandler.h"
#include "XMLContentHandler.h"
@@ -77,13 +80,32 @@
handlers.writeEndElement();
}
- void writeString(StringType type, std::string value) override {
- handlers.writeStartElement("string");
+ void writeTextString(StringType type, std::string value) override {
+ handlers.writeStartElement("text-string",{"type", std::to_string((uint64_t) type)}); // TODO: type name, better attributes
handlers.writeCharacters(value);
handlers.writeEndElement();
}
+ void writeOctetString(std::string value) override {
+ std::stringstream hex;
+ hex << std::hex << std::setfill('0');
+ for (uint8_t b : value) hex << std::setw(2) << (int) b;
+ handlers.writeStartElement("octet-string",{"length", std::to_string(value.size())});
+ handlers.writeCharacters(hex.str());
+ handlers.writeEndElement();
+ }
+
+ void writeBitString(std::vector<bool> value) override {
+ std::stringstream bits;
+ for (bool b : value) bits << (int) b;
+ // for (bool b : value) bits << (b ? ':' : '.'); // TODO: configurable true/false symbols?
+ handlers.writeStartElement("bit-string",{"length", std::to_string(value.size())});
+ handlers.writeCharacters(bits.str());
+ handlers.writeEndElement();
+ }
+
void writeOID(ObjectIdentifier value) override {
+ // TODO: optionally expand into separate elements with additional metadata
handlers.writeStartElement("oid");
handlers.writeCharacters(value.toString());
handlers.writeEndElement();