As mentioned at the end of my previous post KDE Connect iOS Develop Dairy(2) Identity Protocol, the new version KDE Connect protocol needs a TLS/SSL connection to make a completed identification. Indeed, devices use the TLS/SSL connection to communicate with each other, under secure consideration.
In such a connection with asymmetric cryptography, the most important thing is the private key, the public key exchange, and the certificate signed with each device’s private key. This post describes how I added a related library (OpenSSL) and used it to generate these elements.
Investigation
OpenSSL is a widely used library for my purpose. However, there are too many options for each entity. For the private-public key pair, there are several algorithms such as the Elliptic-Curve Digital Signature Algorithm (ECDSA), RSA, etc. What we need to use is precisely the one used by the original KDE Connect.
So, I did an investigation on the original version on KDE Invent.
Implementation in KDE Connect codebase
KDE Connect uses QCA-Qt5 (Qt Cryptographic Architecture), a Qt library providing a straightforward API.
To generate a private key (and its paired public key) with 2048 bits from the RSA algorithm, KDE Connect profits this single line:
// FIXME: We only use QCA here to generate the cert and key, would be nice to get rid of it completely. // The same thing we are doing with QCA could be done invoking openssl (although it's potentially less portable): // openssl req -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout privateKey.pem -days 3650 -out certificate.pem -subj "/O=KDE/OU=KDE Connect/CN=_e6e29ad4_2b31_4b6d_8f7a_9872dbaa9095_"
TL;DR, KDE Connect gets a UUID of the current device, use it as Common Name(CN) to generate a certificate with PKCS10; the certificate is valid from one year before to ten years later; there are 2 other fields: Orgnization(O) set to KDE and Organization Unit(OU) set to `Kde connect. Finally, KDE Connect uses the private key to sign the certificate (we can call it self-sign, because there is no authority).
We can see that the QCA::Certificate constructor is in charge of all of them. Unfortunately, on iOS, it is not so easy to find an all-in-one solution. I needed to find out how it is done in detail.
classQCA_EXPORTCertContext :public CertBase { Q_OBJECT public: /** Standard constructor \param p the provider associated with this context */ CertContext(Provider *p) : CertBase(p, QStringLiteral("cert")) {}
/** Create a self-signed certificate based on the given options and private key. Returns true if successful, otherwise false. If successful, this object becomes the self-signed certificate. If unsuccessful, this object is considered to be in an uninitialized state. \param opts the options to set on the certificate \param priv the key to be used to sign the certificate */ virtualboolcreateSelfSigned(const CertificateOptions &opts, const PKeyContext &priv)= 0;
RSA * rsa; rsa = RSA_generate_key( 2048, /* number of bits for the key - 2048 is a sensible value */ RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */ NULL, /* callback - can be NULL if we aren't displaying progress */ NULL /* callback argument - not needed in this case */ ); EVP_PKEY_assign_RSA(pkey, rsa);
// write into `Documents/rsaPrivate.p12` NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *p12FilePath = NULL; for (NSString *directory in documentDirectories) { NSLog(@"Find %@", directory); p12FilePath = [directory stringByAppendingString:@"/rsaPrivate.p12"]; } if (![[NSFileManager defaultManager] createFileAtPath:p12FilePath contents:nil attributes:nil]) { NSLog(@"Error creating file for P12"); @throw [[NSException alloc] initWithName:@"Fail getP12File" reason:@"Fail Error creating file for P12" userInfo:nil]; }
// get a FILE struct for the P12 file NSFileHandle *outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:p12FilePath]; FILE *p12File = fdopen([outputFileHandle fileDescriptor], "w");
In this post, I described, in general, how I generate and load the private key and certificate in KDE Connect iOS. This aims at preparing a TLS/SSL connection between an iOS device and a device using the current version of KDE Connect.
In the next post, I will tell the TLS/SSL transport in KDE Connect iOS. Thanks for reading!