Skip to content

Commit

Permalink
Add SID V2 support (open-eid#954)
Browse files Browse the repository at this point in the history
IB-6810

Signed-off-by: Raul Metsma <[email protected]>
  • Loading branch information
metsma authored May 31, 2022
1 parent 350b837 commit 20180ed
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 15 deletions.
2 changes: 2 additions & 0 deletions client/Diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ void Diagnostics::generalInfo(QTextStream &s) const
#ifdef CONFIG_URL
<< "<br />CONFIG_URL: " << CONFIG_URL
<< "<br />SID-PROXY-URL: " << Configuration::instance().object().value(QStringLiteral("SID-PROXY-URL")).toString(QStringLiteral(SMARTID_URL))
<< "<br />SIDV2-PROXY-URL: " << Configuration::instance().object().value(QStringLiteral("SIDV2-PROXY-URL")).toString(QStringLiteral(SMARTID_URL))
<< "<br />SID-SK-URL: " << Configuration::instance().object().value(QStringLiteral("SID-SK-URL")).toString(QStringLiteral(SMARTID_URL))
<< "<br />SIDV2-SK-URL: " << Configuration::instance().object().value(QStringLiteral("SIDV2-SK-URL")).toString(QStringLiteral(SMARTID_URL))
<< "<br />MID-PROXY-URL: " << Configuration::instance().object().value(QStringLiteral("MID-PROXY-URL")).toString(QStringLiteral(MOBILEID_URL))
<< "<br />MID-SK-URL: " << Configuration::instance().object().value(QStringLiteral("MID-SK-URL")).toString(QStringLiteral(MOBILEID_URL))
<< "<br />RPUUID: " << (QSettings().value(QStringLiteral("MIDUUID-CUSTOM"), QSettings().contains(QStringLiteral("MIDUUID"))).toBool() ? tr("is set manually") : tr("is set by default"))
Expand Down
2 changes: 1 addition & 1 deletion client/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ void MainWindow::onSignAction(int action, const QString &info1, const QString &i
case SignatureSmartID:
sign([this, info1, info2](const QString &city, const QString &state, const QString &zip, const QString &country, const QString &role) {
SmartIDProgress s(this);
return s.init(info1, info2) &&
return s.init(info1, info2, digiDoc->fileName()) &&
digiDoc->sign(city, state, zip, country, role, &s);
});
break;
Expand Down
53 changes: 40 additions & 13 deletions client/dialogs/SmartIDProgress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ class SmartIDProgress::Private final: public QDialog, public Ui::MobileProgress
QTimeLine *statusTimer = nullptr;
QNetworkAccessManager *manager = nullptr;
QNetworkRequest req;
QString documentNumber, sessionID;
QString documentNumber, sessionID, fileName;
X509Cert cert;
std::vector<unsigned char> signature;
QEventLoop l;
#ifdef CONFIG_URL
QString PROXYURL = Configuration::instance().object().value(QStringLiteral("SID-PROXY-URL")).toString(QStringLiteral(SMARTID_URL));
QString SKURL = Configuration::instance().object().value(QStringLiteral("SID-SK-URL")).toString(QStringLiteral(SMARTID_URL));
QJsonObject config = Configuration::instance().object();
QString PROXYURL = config.value(QStringLiteral("SIDV2-PROXY-URL")).toString(config.value(QStringLiteral("SID-PROXY-URL")).toString(QStringLiteral(SMARTID_URL)));
QString SKURL = config.value(QStringLiteral("SIDV2-SK-URL")).toString(config.value(QStringLiteral("SID-SK-URL")).toString(QStringLiteral(SMARTID_URL)));
#else
QString PROXYURL = QSettings().value(QStringLiteral("SID-PROXY-URL"), QStringLiteral(SMARTID_URL)).toString();
QString SKURL = QSettings().value(QStringLiteral("SID-SK-URL"), QStringLiteral(SMARTID_URL)).toString();
Expand All @@ -87,7 +88,7 @@ SmartIDProgress::SmartIDProgress(QWidget *parent)
: d(new Private(parent))
{
const_cast<QLoggingCategory&>(SIDLog()).setEnabled(QtDebugMsg,
true || QFile::exists(QStringLiteral("%1/%2.log").arg(QDir::tempPath(), qApp->applicationName())));
QFile::exists(QStringLiteral("%1/%2.log").arg(QDir::tempPath(), qApp->applicationName())));
d->setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint);
d->setupUi(d);
d->move(parent->geometry().center() - d->geometry().center());
Expand Down Expand Up @@ -131,7 +132,7 @@ background-color: #007aff;
QList<QSslCertificate> trusted;
#ifdef CONFIG_URL
ssl.setCaCertificates({});
for(const QJsonValue cert: Configuration::instance().object().value(QStringLiteral("CERT-BUNDLE")).toArray())
for(const QJsonValue cert: d->config.value(QStringLiteral("CERT-BUNDLE")).toArray())
trusted << QSslCertificate(QByteArray::fromBase64(cert.toString().toLatin1()), QSsl::Der);
#endif
d->req.setSslConfiguration(ssl);
Expand Down Expand Up @@ -247,10 +248,17 @@ background-color: #007aff;
else if(result.value(QStringLiteral("state")).toString() != QStringLiteral("RUNNING"))
{
QString endResult = result.value(QStringLiteral("result")).toObject().value(QStringLiteral("endResult")).toString();
if(endResult == QStringLiteral("USER_REFUSED"))
if(endResult == QStringLiteral("USER_REFUSED") ||
endResult == QStringLiteral("USER_REFUSED_CERT_CHOICE") ||
endResult == QStringLiteral("USER_REFUSED_DISPLAYTEXTANDPIN") ||
endResult == QStringLiteral("USER_REFUSED_VC_CHOICE") ||
endResult == QStringLiteral("USER_REFUSED_CONFIRMATIONMESSAGE") ||
endResult == QStringLiteral("USER_REFUSED_CONFIRMATIONMESSAGE_WITH_VC_CHOICE"))
returnError(tr("User denied or cancelled"));
else if(endResult == QStringLiteral("TIMEOUT"))
returnError(tr("Failed to sign container. Your Smart-ID transaction has expired or user account not found."));
else if(endResult == QStringLiteral("REQUIRED_INTERACTION_NOT_SUPPORTED_BY_APP"))
returnError(tr("Failed to sign container. You need to update your Smart-ID application to sign documents in DigiDoc4 Client."));
else if(endResult == QStringLiteral("WRONG_VC"))
returnError(tr("Error: an incorrect control code was chosen"));
else if(endResult == QStringLiteral("DOCUMENT_UNUSABLE"))
Expand Down Expand Up @@ -297,21 +305,31 @@ X509Cert SmartIDProgress::cert() const
return d->cert;
}

bool SmartIDProgress::init(const QString &country, const QString &idCode)
bool SmartIDProgress::init(const QString &country, const QString &idCode, const QString &fileName)
{
if(!d->UUID.isEmpty() && QUuid(d->UUID).isNull())
{
WarningDialog(tr("Failed to send request. Check your %1 service access settings.").arg(tr("Smart-ID")), {}, d->parentWidget()).exec();
return false;
}
QFileInfo info(fileName);
QString displayFile = info.completeBaseName();
if(displayFile.size() > 6)
displayFile = displayFile.left(3) + QStringLiteral("...") + displayFile.right(3);
displayFile += QStringLiteral(".") + info.suffix();
d->fileName = displayFile;
d->sessionID.clear();
QByteArray data = QJsonDocument({
{"relyingPartyUUID", d->UUID.isEmpty() ? QStringLiteral("00000000-0000-0000-0000-000000000000") : d->UUID},
{"relyingPartyName", d->NAME},
{"certificateLevel", "QUALIFIED"},
{"nonce", QUuid::createUuid().toString().remove('-').mid(1, 30)}
}).toJson();
d->req.setUrl(QUrl(QStringLiteral("%1/certificatechoice/pno/%2/%3").arg(d->URL(), country, idCode)));
if (d->req.url().path().contains(QStringLiteral("v1"), Qt::CaseInsensitive)) {
d->req.setUrl(QUrl(QStringLiteral("%1/certificatechoice/pno/%2/%3").arg(d->URL(), country, idCode)));
} else {
d->req.setUrl(QUrl(QStringLiteral("%1/certificatechoice/etsi/PNO%2-%3").arg(d->URL(), country, idCode)));
}
qCDebug(SIDLog).noquote() << d->req.url() << data;
d->manager->post(d->req, data);
d->info->setText(tr("Open the Smart-ID application on your smart device and confirm device for signing."));
Expand Down Expand Up @@ -344,17 +362,26 @@ std::vector<unsigned char> SmartIDProgress::sign(const std::string &method, cons
"and enter Smart-ID PIN2-code."));
d->code->setAccessibleName(QStringLiteral("%1 %2. %3").arg(d->controlCode->text(), d->code->text(), d->info->text()));

QByteArray data = QJsonDocument({
QJsonObject req{
{"relyingPartyUUID", (d->UUID.isEmpty() ? QStringLiteral("00000000-0000-0000-0000-000000000000") : d->UUID)},
{"relyingPartyName", d->NAME},
{"certificateLevel", "QUALIFIED"},
{"hash", QString(QByteArray::fromRawData((const char*)digest.data(), int(digest.size())).toBase64())},
{"hashType", digestMethod},
{"requestProperties", QJsonObject{{"vcChoice", true}}},
{"displayText", "%1"}
}).toJson();
};
QString escape = tr("Sign document");
if (d->req.url().path().contains(QStringLiteral("v1"), Qt::CaseInsensitive)) {
req[QStringLiteral("requestProperties")] = QJsonObject{{"vcChoice", true}};
req[QStringLiteral("displayText")] = "%1";
} else {
req[QStringLiteral("allowedInteractionsOrder")] = QJsonArray{QJsonObject{
{"type", "confirmationMessageAndVerificationCodeChoice"},
{"displayText200", "%1"}
}};
escape = QStringLiteral("%1 %2").arg(tr("Sign document"), d->fileName);
}
// Workaround SID proxy issues
data = QString::fromUtf8(data).arg(escapeUnicode(tr("Sign document"))).toUtf8();
QByteArray data = QString::fromUtf8(QJsonDocument(req).toJson()).arg(escapeUnicode(escape)).toUtf8();
d->req.setUrl(QUrl(QStringLiteral("%1/signature/document/%2").arg(d->URL(), d->documentNumber)));
qCDebug(SIDLog).noquote() << d->req.url() << data;
d->manager->post(d->req, data);
Expand Down
2 changes: 1 addition & 1 deletion client/dialogs/SmartIDProgress.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class SmartIDProgress final: public digidoc::Signer
explicit SmartIDProgress(QWidget *parent = nullptr);
~SmartIDProgress() final;
digidoc::X509Cert cert() const final;
bool init(const QString &country, const QString &idCode);
bool init(const QString &country, const QString &idCode, const QString &fileName);
std::vector<unsigned char> sign(const std::string &method, const std::vector<unsigned char> &digest) const final;

private:
Expand Down
4 changes: 4 additions & 0 deletions client/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,10 @@ and enter Smart-ID PIN2-code.</translation>
<source>Failed to sign container. Your Smart-ID transaction has expired or user account not found.</source>
<translation>Failed to sign container. Your Smart-ID transaction has expired or user account not found.</translation>
</message>
<message>
<source>Failed to sign container. You need to update your Smart-ID application to sign documents in DigiDoc4 Client.</source>
<translation>Failed to sign container. You need to update your Smart-ID application to sign documents in DigiDoc4 Client.</translation>
</message>
</context>
<context>
<name>NoCardInfo</name>
Expand Down
4 changes: 4 additions & 0 deletions client/translations/et.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1929,6 +1929,10 @@ ja sisesta nutiseadmes Smart-ID PIN2-kood.</translation>
<source>Failed to sign container. Your Smart-ID transaction has expired or user account not found.</source>
<translation>Ümbriku allkirjastamine ebaõnnestus. Sinu Smart-ID toiming aegus või kontot ei leitud.</translation>
</message>
<message>
<source>Failed to sign container. You need to update your Smart-ID application to sign documents in DigiDoc4 Client.</source>
<translation>Ümbriku allkirjastamine ebaõnnestus. DigiDoc4 kliendis allkirjastamiseks pead Smart-ID rakendust uuendama.</translation>
</message>
</context>
<context>
<name>NoCardInfo</name>
Expand Down
4 changes: 4 additions & 0 deletions client/translations/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,10 @@ and enter Smart-ID PIN2-code.</source>
<source>Failed to sign container. Your Smart-ID transaction has expired or user account not found.</source>
<translation>Не удалось подписать контейнер. Срок действия вашей операции Smart-ID истек или учетная запись не найдена.</translation>
</message>
<message>
<source>Failed to sign container. You need to update your Smart-ID application to sign documents in DigiDoc4 Client.</source>
<translation>Не удалось подписать контейнер. Для подписания с помощью Smart-ID в программе DigiDoc4 клиент нужно обновить приложение Smart-ID.</translation>
</message>
</context>
<context>
<name>NoCardInfo</name>
Expand Down

0 comments on commit 20180ed

Please sign in to comment.