File indexing completed on 2024-11-24 04:44:40

0001 /*
0002  * SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003  * SPDX-License-Identifier: LGPL-2.0-or-later
0004  */
0005 
0006 #include "irmapublickey_p.h"
0007 
0008 #include "openssl/bignum_p.h"
0009 
0010 #include <QDebug>
0011 #include <QFile>
0012 #include <QXmlStreamReader>
0013 
0014 // see https://pkg.go.dev/github.com/privacybydesign/gabi@v0.0.0-20210816093228-75a6590e506c/gabikeys#PublicKey
0015 
0016 IrmaPublicKey::IrmaPublicKey() = default;
0017 
0018 bool IrmaPublicKey::isValid() const
0019 {
0020     return N && Z && S && std::all_of(R.begin(), R.end(), [](const auto &r) { return r.get() != nullptr; });
0021 }
0022 
0023 // see https://github.com/minvws/gabi/blob/idemix_origin/sysparams.go#L21
0024 int IrmaPublicKey::LePrime() const
0025 {
0026     return 120;
0027 }
0028 
0029 int IrmaPublicKey::Lh() const
0030 {
0031     return 256;
0032 }
0033 
0034 int IrmaPublicKey::Lm() const
0035 {
0036     switch (BN_num_bits(N.get())) {
0037         case 1024:
0038         case 2048:
0039             return 256;
0040         case 4096:
0041             return 512;
0042     }
0043     return 0;
0044 }
0045 
0046 int IrmaPublicKey::Lstatzk() const
0047 {
0048     switch (BN_num_bits(N.get())) {
0049         case 1024:
0050             return 80;
0051         case 2048:
0052         case 4096:
0053             return 128;
0054     }
0055     return 0;
0056 }
0057 
0058 // and https://github.com/minvws/gabi/blob/idemix_origin/sysparams.go#L60
0059 int IrmaPublicKey::Le() const
0060 {
0061     return Lstatzk() + Lh() + Lm() + 5;
0062 }
0063 
0064 int IrmaPublicKey::LeCommit() const
0065 {
0066     return LePrime() + Lstatzk() + Lh();
0067 }
0068 
0069 int IrmaPublicKey::LmCommit() const
0070 {
0071     return Lm() + Lstatzk() + Lh();
0072 }
0073 
0074 
0075 IrmaPublicKey IrmaPublicKeyLoader::load(const QString &keyId)
0076 {
0077     IrmaPublicKey pk;
0078 
0079     QFile pkFile(QLatin1String(":/org.kde.khealthcertificate/nl-coronacheck/keys/") + keyId + QLatin1String(".xml"));
0080     if (!pkFile.open(QFile::ReadOnly)) {
0081         qWarning() << "Failed to find IRMA public key:" << keyId;
0082         return pk;
0083     }
0084 
0085     QXmlStreamReader reader(&pkFile);
0086     while (!reader.atEnd() && !reader.hasError()) {
0087         reader.readNextStartElement();
0088         if (reader.name() == QLatin1String("n")) {
0089             pk.N = Bignum::fromDecimalString(reader.readElementText());
0090         }
0091         else if (reader.name() == QLatin1String("Z")) {
0092             pk.Z = Bignum::fromDecimalString(reader.readElementText());
0093         }
0094         else if (reader.name() == QLatin1String("S")) {
0095             pk.S = Bignum::fromDecimalString(reader.readElementText());
0096         }
0097         else if (reader.name() == QLatin1String("Bases")) {
0098             const auto num = reader.attributes().value(QLatin1String("num")).toInt();
0099             pk.R.reserve(num);
0100         }
0101         else if (reader.name().startsWith(QLatin1String("Base_"))) {
0102             pk.R.push_back(Bignum::fromDecimalString(reader.readElementText()));
0103         }
0104     }
0105 
0106     return pk;
0107 }