29#include "certviewdlg.h"
30#include "keyselectdlg.h"
31#include "pkcs11configdlg/pkcs11configdlg.h"
32#include "ui_mainwin.h"
35#include "import_plugins.h"
38#define VERSION "1.0.0"
43 QPixmap cert, crl, keybundle, pgppub, pgpsec;
72 s =
Operation::tr(
"Root CA is marked to reject the specified purpose");
75 s =
Operation::tr(
"Certificate not trusted for the required purpose");
93 s =
Operation::tr(
"Maximum certificate chain length exceeded");
138 s =
Operation::tr(
"Certificate and private key don't match.");
170class SignOperation :
public Operation
175 CertItemStore *store;
178 CertItemPrivateLoader *loader;
191 loader =
new CertItemPrivateLoader(store,
this);
192 connect(loader, SIGNAL(finished()), SLOT(loader_finished()));
198 void finished(
const QString &sig);
201 void loader_finished()
207 if (privateKey.
isNull()) {
212 CertItem item = store->itemFromId(
id);
219 connect(msg, SIGNAL(bytesWritten(
int)), SLOT(msg_bytesWritten(
int)));
220 connect(msg, SIGNAL(finished()), SLOT(msg_finished()));
233 pending += buf.
size();
237 void msg_bytesWritten(
int x)
241 if (in.
isEmpty() && pending == 0)
253 emit error(
tr(
"Error during sign operation.\nReason: %1").arg(str));
264class VerifyOperation :
public Operation
284 connect(msg, SIGNAL(bytesWritten(
int)), SLOT(msg_bytesWritten(
int)));
285 connect(msg, SIGNAL(finished()), SLOT(msg_finished()));
301 pending += buf.
size();
305 void msg_bytesWritten(
int x)
309 if (in.
isEmpty() && pending == 0)
321 emit error(
tr(
"Error during verify operation.\nReason: %1").arg(str));
330 QString str = smsIdentityToString(signer);
331 emit error(
tr(
"Verification failed!\nReason: %1").arg(str));
346 for (
int n = 0; n <
hex.count(); ++n) {
347 if (n != 0 && n % 2 == 0)
359 CertItemStore *users, *roots;
362 QAction *actionView, *actionRename, *actionRemove;
364 int auto_import_req_id;
370 , auto_import_req_id(-1)
375 g_icons->cert =
QPixmap(
":/gfx/icons/cert16.png");
376 g_icons->crl =
QPixmap(
":/gfx/icons/crl16.png");
377 g_icons->keybundle =
QPixmap(
":/gfx/icons/keybundle16.png");
378 g_icons->pgppub =
QPixmap(
":/gfx/icons/publickey16.png");
379 g_icons->pgpsec =
QPixmap(
":/gfx/icons/keypair16.png");
382 printf(
"Warning: not all icons loaded\n");
384 users =
new CertItemStore(
this);
385 roots =
new CertItemStore(
this);
390 connect(users, SIGNAL(addSuccess(
int,
int)), SLOT(users_addSuccess(
int,
int)));
391 connect(users, SIGNAL(addFailed(
int)), SLOT(users_addFailed(
int)));
393 actionView =
new QAction(
tr(
"&View"),
this);
394 actionRename =
new QAction(
tr(
"Re&name"),
this);
395 actionRemove =
new QAction(
tr(
"Rem&ove"),
this);
397 connect(ui.actionLoadIdentityFile, SIGNAL(triggered()), SLOT(load_file()));
398 connect(ui.actionLoadIdentityEntry, SIGNAL(triggered()), SLOT(load_device()));
399 connect(ui.actionLoadAuthority, SIGNAL(triggered()), SLOT(load_root()));
400 connect(ui.actionConfigurePkcs11, SIGNAL(triggered()), SLOT(mod_config()));
401 connect(ui.actionQuit, SIGNAL(triggered()), SLOT(
close()));
402 connect(ui.actionAbout, SIGNAL(triggered()), SLOT(about()));
403 connect(ui.pb_sign, SIGNAL(clicked()), SLOT(do_sign()));
404 connect(ui.pb_verify, SIGNAL(clicked()), SLOT(do_verify()));
406 connect(actionView, SIGNAL(triggered()), SLOT(item_view()));
407 connect(actionRename, SIGNAL(triggered()), SLOT(item_rename()));
408 connect(actionRemove, SIGNAL(triggered()), SLOT(item_remove()));
410 ui.pb_sign->setEnabled(
false);
412 ui.lv_users->setModel(users);
413 connect(ui.lv_users->selectionModel(),
420 SLOT(users_customContextMenuRequested(
const QPoint &)));
422 ui.lv_authorities->setModel(roots);
427 SLOT(roots_customContextMenuRequested(
const QPoint &)));
433 QSettings settings(
"Affinix",
"CMS Signer");
434 ulist = settings.
value(
"users").toStringList();
435 rlist = settings.
value(
"roots").toStringList();
447 QSettings settings(
"Affinix",
"CMS Signer");
448 settings.setValue(
"users", ulist);
449 settings.setValue(
"roots", rlist);
455 void setIcons(CertItemStore *store)
457 store->setIcon(CertItemStore::IconCert, g_icons->cert);
458 store->setIcon(CertItemStore::IconCrl, g_icons->crl);
459 store->setIcon(CertItemStore::IconKeyBundle, g_icons->keybundle);
460 store->setIcon(CertItemStore::IconPgpPub, g_icons->pgppub);
461 store->setIcon(CertItemStore::IconPgpSec, g_icons->pgpsec);
472 foreach (
const CertItem &i, roots->items())
476 foreach (
const CertItem &i, users->items()) {
486 return chain.
complete(allCerts().certificates());
498 users->addFromFile(fileName);
503 KeySelectDlg *w =
new KeySelectDlg(
this);
511 w->setIcon(KeySelectDlg::IconCert, g_icons->cert);
512 w->setIcon(KeySelectDlg::IconCrl, g_icons->crl);
513 w->setIcon(KeySelectDlg::IconKeyBundle, g_icons->keybundle);
514 w->setIcon(KeySelectDlg::IconPgpPub, g_icons->pgppub);
515 w->setIcon(KeySelectDlg::IconPgpSec, g_icons->pgpsec);
521 users->addFromKeyStore(entry);
537 roots->addUser(cert);
540 void users_addSuccess(
int req_id,
int id)
542 if (req_id == auto_import_req_id) {
543 auto_import_req_id = -1;
545 CertItem i = users->itemFromId(
id);
549 tr(
"This signature was made by a previously unknown user, and so the "
550 "user has now been added to the keyring as \"%1\".")
557 ui.lv_users->selectionModel()->select(users->
index(users->rowFromId(
id)),
564 void users_addFailed(
int req_id)
573 if (!Pkcs11ConfigDlg::isSupported()) {
575 this,
tr(
"Error"),
tr(
"No provider available supporting standard PKCS#11 configuration."));
579 Pkcs11ConfigDlg *w =
new Pkcs11ConfigDlg(
this);
587 Q_UNUSED(deselected);
590 if (!selected.
indexes().isEmpty()) {
596 if (at != -1 && users->itemFromRow(at).isUsable())
599 if (usable && !ui.pb_sign->isEnabled())
600 ui.pb_sign->setEnabled(
true);
601 else if (!usable && ui.pb_sign->isEnabled())
602 ui.pb_sign->setEnabled(
false);
607 if (ui.lv_users->hasFocus()) {
608 QItemSelection selection = ui.lv_users->selectionModel()->selection();
609 if (selection.
indexes().isEmpty())
612 users_view(index.
row());
615 QItemSelection selection = ui.lv_authorities->selectionModel()->selection();
616 if (selection.
indexes().isEmpty())
619 roots_view(index.
row());
625 if (ui.lv_users->hasFocus()) {
626 QItemSelection selection = ui.lv_users->selectionModel()->selection();
627 if (selection.
indexes().isEmpty())
630 users_rename(index.
row());
633 QItemSelection selection = ui.lv_authorities->selectionModel()->selection();
634 if (selection.
indexes().isEmpty())
637 roots_rename(index.
row());
643 if (ui.lv_users->hasFocus()) {
644 QItemSelection selection = ui.lv_users->selectionModel()->selection();
645 if (selection.
indexes().isEmpty())
648 users_remove(index.
row());
651 QItemSelection selection = ui.lv_authorities->selectionModel()->selection();
652 if (selection.
indexes().isEmpty())
655 roots_remove(index.
row());
659 void users_view(
int at)
661 CertItem i = users->itemFromRow(at);
662 CertViewDlg *w =
new CertViewDlg(complete(i.certificateChain()),
this);
667 void users_rename(
int at)
670 ui.lv_users->setFocus();
671 ui.lv_users->setCurrentIndex(index);
672 ui.lv_users->selectionModel()->select(
674 ui.lv_users->edit(index);
677 void users_remove(
int at)
679 users->removeItem(users->idFromRow(at));
682 void roots_view(
int at)
684 CertItem i = roots->itemFromRow(at);
685 CertViewDlg *w =
new CertViewDlg(complete(i.certificateChain()),
this);
690 void roots_rename(
int at)
693 ui.lv_authorities->setFocus();
694 ui.lv_authorities->setCurrentIndex(index);
695 ui.lv_authorities->selectionModel()->select(
697 ui.lv_authorities->edit(index);
700 void roots_remove(
int at)
702 roots->removeItem(roots->idFromRow(at));
707 CertViewDlg *w =
new CertViewDlg(complete(chain), (
QWidget *)
sender());
712 void users_customContextMenuRequested(
const QPoint &
pos)
714 QItemSelection selection = ui.lv_users->selectionModel()->selection();
715 if (selection.
indexes().isEmpty())
719 menu.addAction(actionView);
720 menu.addAction(actionRename);
721 menu.addAction(actionRemove);
722 menu.exec(ui.lv_users->viewport()->mapToGlobal(
pos));
725 void roots_customContextMenuRequested(
const QPoint &
pos)
727 QItemSelection selection = ui.lv_authorities->selectionModel()->selection();
728 if (selection.
indexes().isEmpty())
732 menu.addAction(actionView);
733 menu.addAction(actionRename);
734 menu.addAction(actionRemove);
735 menu.exec(ui.lv_authorities->viewport()->mapToGlobal(
pos));
740 QItemSelection selection = ui.lv_users->selectionModel()->selection();
741 if (selection.
indexes().isEmpty())
744 int at = index.
row();
748 op =
new SignOperation(ui.te_data->toPlainText().toUtf8(), users, users->idFromRow(at), cms,
this);
749 connect(op, SIGNAL(loadError()), SLOT(sign_loadError()));
763 foreach (
const CertItem &i, roots->items())
769 foreach (
const CertItem &i, users->items()) {
776 if (!self_signed_verify_cert.
isNull()) {
785 op =
new VerifyOperation(ui.te_data->toPlainText().toUtf8(), ui.te_sig->toPlainText().toUtf8(), cms,
this);
786 connect(op, SIGNAL(finished()), SLOT(verify_finished()));
793 int maj = (ver >> 16) & 0xff;
794 int min = (ver >> 8) & 0xff;
795 int bug = ver & 0xff;
797 verstr.sprintf(
"%d.%d.%d", maj, min, bug);
800 str +=
tr(
"CMS Signer version %1 by Justin Karneges").
arg(VERSION) +
'\n';
801 str +=
tr(
"A simple tool for creating and verifying digital signatures.") +
'\n';
803 str +=
tr(
"Using QCA version %1").
arg(verstr) +
'\n';
805 str +=
tr(
"Icons by Jason Kim") +
'\n';
819 void sign_loadError()
827 void sign_finished(
const QString &sig)
832 ui.te_sig->setPlainText(sig);
837 void sign_error(
const QString &msg)
847 void verify_finished()
860 for (
int n = 0; n < items.
count(); ++n) {
861 const CertItem &i = items[n];
870 auto_import_req_id = users->addUser(chain);
875 users->updateChain(users->idFromRow(at), chain);
889 void verify_error(
const QString &msg)
903 tr(
"Self-signed certificate"),
904 tr(
"<qt>The signature is made by an unknown user, and the certificate is self-signed.<br>\n"
906 "<nobr>Common Name: %1</nobr><br>\n"
907 "<nobr>SHA1 Fingerprint: %2</nobr><br>\n"
909 "Trust the certificate?</qt>")
910 .arg(cert.
commonName(), get_fingerprint(cert)),
915 self_signed_verify_cert = cert;
928int main(
int argc,
char **argv)
933 qapp.setApplicationName(
MainWin::tr(
"CMS Signer"));
938 qapp.applicationName() +
": " +
MainWin::tr(
"Error"),
940 "No support for CMS is available. Please install an appropriate QCA plugin, such as qca-ossl."));
Cryptographic Message Syntax messaging system.
void setTrustedCertificates(const CertificateCollection &trusted)
Set the trusted certificates to use for the messages built using this CMS object.
A chain of related Certificates.
const Certificate & primary() const
Return the primary (end-user) Certificate.
CertificateChain complete(const QList< Certificate > &issuers=QList< Certificate >(), Validity *result=nullptr) const
Complete a certificate chain for the primary certificate, using the rest of the certificates in the c...
Bundle of Certificates and CRLs.
void addCertificate(const Certificate &cert)
Append a Certificate to this collection.
Public Key (X.509) certificate.
QString commonName() const
The common name of the subject of the certificate.
bool isSelfSigned() const
Test if the Certificate is self-signed.
static Certificate fromPEMFile(const QString &fileName, ConvertResult *result=nullptr, const QString &provider=QString())
Import the certificate from a file.
bool isNull() const
Test if the certificate is empty (null)
QByteArray toDER() const
Export the Certificate into a DER format.
General class for hashing algorithms.
QString hashToString(const MemoryRegion &array)
Hash a byte array, returning it as a printable string
Convenience method for initialising and cleaning up QCA.
Single entry in a KeyStore.
static void start()
Initialize all key store providers.
bool isNull() const
Test if the key is null (empty)
virtual QString credit() const
Optional credit text for the provider.
Key for SecureMessage system.
void setX509PrivateKey(const PrivateKey &k)
Set the private key part of this X.509 key.
bool isNull() const
Returns true for null object.
CertificateChain x509CertificateChain() const
The X.509 certificate chain (public part) for this key.
void setX509CertificateChain(const CertificateChain &c)
Set the public key part of this X.509 key.
IdentityResult identityResult() const
get the results of the identity check on this signature
@ InvalidSignature
valid key provided, but signature failed
@ Valid
indentity is verified, matches signature
@ InvalidKey
invalid key provided
SecureMessageKey key() const
get the key associated with this signature
Validity keyValidity() const
get the results of the key validation check on this signature
Class representing a secure message.
bool success() const
Indicates whether or not the operation was successful or failed.
QByteArray signature() const
The signature for the message.
void setFormat(Format f)
Set the Format used for messages.
void startSign(SignMode m=Message)
Start a signing operation.
SecureMessageSignature signer() const
Information on the signer for the message.
void setSigner(const SecureMessageKey &key)
Set the signer for a signed message.
void startVerify(const QByteArray &detachedSig=QByteArray())
Start a verification operation.
Error
Errors for secure messages.
@ ErrorUnknown
other error
@ ErrorSignerExpired
signing key is expired
@ ErrorEncryptExpired
encrypting key is expired
@ ErrorSignerInvalid
signing key is invalid in some way
@ ErrorEncryptUntrusted
encrypting key is untrusted
@ ErrorEncryptInvalid
encrypting key is invalid in some way
@ ErrorCertKeyMismatch
certificate and private key don't match
@ ErrorFormat
input format was bad
@ ErrorPassphrase
passphrase was either wrong or not provided
@ ErrorNeedCard
pgp card is missing
void end()
Complete an operation.
@ Detached
the signature is detached
@ Ascii
PEM/ascii-armored.
Error errorCode() const
Returns the failure code.
void update(const QByteArray &in)
Process a message (or the next part of a message) in the current operation.
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
Validity
The validity (or otherwise) of a certificate.
@ ErrorValidityUnknown
Validity is unknown.
@ ErrorRevoked
The certificate has been revoked.
@ ErrorUntrusted
The certificate is not trusted.
@ ErrorExpired
The certificate has expired, or is not yet valid (e.g.
@ ErrorPathLengthExceeded
The path length from the root CA to this certificate is too long.
@ ErrorSignatureFailed
The signature does not match.
@ ErrorInvalidPurpose
The purpose does not match the intended usage.
@ ErrorExpiredCA
The Certificate Authority has expired.
@ ErrorSelfSigned
The certificate is self-signed, and is not found in the list of trusted certificates.
@ ErrorInvalidCA
The Certificate Authority is invalid.
@ ValidityGood
The certificate is valid.
@ ErrorRejected
The root CA rejected the certificate purpose.
QCA_EXPORT bool isSupported(const char *features, const QString &provider=QString())
Test if a capability (algorithm) is available.
QCA_EXPORT ProviderList providers()
Return a list of the current providers.
QCA_EXPORT CertificateCollection systemStore()
Get system-wide root Certificate Authority (CA) certificates.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isEmpty() const const
QByteArray mid(qsizetype pos, qsizetype len) const const
qsizetype size() const const
QCA_EXPORT int qcaVersion()
The current version of QCA.
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
QModelIndexList indexes() const const
qsizetype count() const const
T value(qsizetype i) const const
void about(QWidget *parent, const QString &title, const QString &text)
StandardButton critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QObject * sender() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
QTextStream & hex(QTextStream &stream)