File indexing completed on 2024-05-19 05:17:26
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 0003 * SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #include "../src/lib/nl-coronacheck/nlbase45.cpp" 0007 #include "../src/lib/openssl/opensslpp_p.h" 0008 0009 #include <QDebug> 0010 #include <QFile> 0011 0012 // creative string encoding... 0013 static QByteArray decodeByteArray(const uint8_t *&it, std::size_t length) 0014 { 0015 auto ai = openssl::asn1_integer_ptr(d2i_ASN1_INTEGER(nullptr, &it, length)); 0016 0017 auto bn = openssl::bn_ptr(BN_new()); 0018 BN_zero(bn.get()); 0019 for (auto i = 0; i < ai->length; ++i) { 0020 BN_mul_word(bn.get(), 1 << 8); 0021 BN_add_word(bn.get(), ai->data[i]); 0022 } 0023 BN_div_word(bn.get(), 2); 0024 0025 QByteArray s; 0026 s.resize(BN_num_bytes(bn.get())); 0027 BN_bn2bin(bn.get(), reinterpret_cast<uint8_t*>(s.data())); 0028 0029 return s; 0030 } 0031 0032 static void dumpMetaData(const QByteArray &md) 0033 { 0034 long int length = 0; 0035 int tag = 0, asn1Class = 0; 0036 auto it = reinterpret_cast<const uint8_t*>(md.constData()); 0037 const auto endIt = it + md.size(); 0038 ASN1_get_object(&it, &length, &tag, &asn1Class, md.size()); 0039 // qDebug() << length << tag << asn1Class << ASN1_tag2str(tag); 0040 0041 while (it != endIt) { 0042 auto it2 = it; 0043 ASN1_get_object(&it, &length, &tag, &asn1Class, std::distance(it, endIt)); 0044 if (tag == V_ASN1_EOC && asn1Class == 0x0) { 0045 break; 0046 } 0047 // qDebug() << length << tag << asn1Class << ASN1_tag2str(tag); 0048 if (tag == V_ASN1_OCTET_STRING) { 0049 auto os = openssl::asn1_octet_string_ptr(d2i_ASN1_OCTET_STRING(nullptr, &it2, length + std::distance(it2, it))); 0050 qDebug() << "version:" << QByteArray((const char*)os->data, os->length); 0051 it = it2; 0052 } else if (tag == V_ASN1_PRINTABLESTRING) { 0053 auto ps = openssl::asn1_printable_string_ptr(d2i_ASN1_PRINTABLESTRING(nullptr, &it2, length + std::distance(it2, it))); 0054 qDebug() << "issuer key:" << QByteArray((const char*)ps->data, ps->length); 0055 it = it2; 0056 } else { 0057 it += length; 0058 } 0059 } 0060 } 0061 0062 static const char *field_names[] = { 0063 "isSpecimen", 0064 "isPaperProof", 0065 "validFrom", 0066 "validForHours", 0067 "firstNameInitial", 0068 "lastNameInitial", 0069 "birthDay", 0070 "birthMonth" 0071 }; 0072 0073 static void dumpInnerSequence(const uint8_t *&it, const uint8_t *endIt) 0074 { 0075 long int length = 0; 0076 int tag = 0, asn1Class = 0; 0077 0078 // metadata field 0079 auto it2 = it; 0080 ASN1_get_object(&it, &length, &tag, &asn1Class, std::distance(it, endIt)); 0081 dumpMetaData(decodeByteArray(it2, length + std::distance(it2, it))); 0082 it = it2; 0083 0084 // string fields 0085 int i = 0; 0086 while (it != endIt) { 0087 it2 = it; 0088 ASN1_get_object(&it, &length, &tag, &asn1Class, std::distance(it, endIt)); 0089 if (tag == V_ASN1_EOC && asn1Class == 0x0) { 0090 break; 0091 } 0092 // qDebug() << length << tag << asn1Class << ASN1_tag2str(tag); 0093 qDebug() << field_names[i++] << decodeByteArray(it2, length + std::distance(it2, it)); 0094 it = it2; 0095 } 0096 } 0097 0098 static void dumpOuterSequence(const uint8_t *&it, const uint8_t *endIt) 0099 { 0100 long int length = 0; 0101 int tag = 0, asn1Class = 0; 0102 while (it != endIt) { 0103 ASN1_get_object(&it, &length, &tag, &asn1Class, std::distance(it, endIt)); 0104 if (tag == V_ASN1_EOC && asn1Class == 0x0) { 0105 break; 0106 } 0107 qDebug() << length << tag << asn1Class << ASN1_tag2str(tag); 0108 if (tag == V_ASN1_SEQUENCE) { 0109 dumpInnerSequence(it, it + length); 0110 } else { 0111 // TODO these fields have to be the signature 0112 it += length; 0113 } 0114 } 0115 } 0116 0117 int main(int argc, char **argv) 0118 { 0119 QFile f; 0120 f.open(stdin, QFile::ReadOnly); 0121 const auto in = f.readAll(); 0122 0123 // strip prefix 0124 if (!in.startsWith("NL2:")) { 0125 return 1; 0126 } 0127 0128 // "base45" decode 0129 const auto base45Decoded = NLBase45::decode(in.begin() + 4, in.end()); 0130 // qDebug() << base45Decoded; 0131 0132 long int length = 0; 0133 int tag = 0, asn1Class = 0; 0134 auto it = reinterpret_cast<const uint8_t*>(base45Decoded.constData()); 0135 ASN1_get_object(&it, &length, &tag, &asn1Class, base45Decoded.size()); 0136 qDebug() << length << tag << asn1Class << ASN1_tag2str(tag); 0137 dumpOuterSequence(it, it + length); 0138 0139 return 0; 0140 }