QCA::PrivateKey EncryptioNgSimliteDecryptor::getPrivateKey(const Key &key) { QByteArray keyData = key.key().toByteArray().trimmed(); if (!keyData.startsWith(BEGIN_RSA_PRIVATE_KEY) || !keyData.endsWith(END_RSA_PRIVATE_KEY)) { Valid = false; return QCA::PrivateKey(); } keyData = keyData.mid(BEGIN_RSA_PRIVATE_KEY_LENGTH, keyData.length() - BEGIN_RSA_PRIVATE_KEY_LENGTH - END_RSA_PRIVATE_KEY_LENGTH).replace('\r', "").trimmed(); QCA::SecureArray certificate; QCA::Base64 decoder; decoder.setLineBreaksEnabled(true); certificate = decoder.decode(keyData); // just some fake security added keyData.fill(' ', keyData.size()); keyData.clear(); if (!decoder.ok()) { Valid = false; return QCA::PrivateKey(); } PKCS1Certificate::ConversionStatus status; PKCS1Certificate pkcs1; QCA::PrivateKey privateKey = pkcs1.privateKeyFromDER(certificate, status); if (PKCS1Certificate::OK != status) { Valid = false; return QCA::PrivateKey(); } if (!privateKey.canDecrypt()) { Valid = false; return QCA::PrivateKey(); } Valid = true; return privateKey; }
int main(int argc, char **argv) { QCA::Initializer qcaInit; QCoreApplication app(argc, argv); if(argc < 3) { printf("usage: mozcerts [certdata.txt] [outfile.pem]\n"); return 0; } QFile infile(argv[1]); if(!infile.open(QFile::ReadOnly)) { fprintf(stderr, "Error opening input file\n"); return 1; } QFile outfile(argv[2]); if(!outfile.open(QFile::WriteOnly | QFile::Truncate)) { fprintf(stderr, "Error opening output file\n"); return 1; } int count = 0; QString name; QTextStream ts(&infile); while(!ts.atEnd()) { QString line = ts.readLine(); if(QRegExp("^#").indexIn(line) != -1) continue; if(QRegExp("^\\s*$").indexIn(line) != -1) continue; line = line.trimmed(); if(QRegExp("CKA_LABEL").indexIn(line) != -1) { QStringList list = splitWithQuotes(line, ' '); if(list.count() != 3) continue; name = list[2]; // make an output filename based on the name //outname = name.replace(QRegExp("\\/"), "_") // .replace(QRegExp("\\s+"), "_") // .replace(QRegExp("[()]"), "=") // .replace(QRegExp(","), "_") + ".pem"; continue; } else if(QRegExp("CKA_VALUE MULTILINE_OCTAL").indexIn(line) != -1) { QByteArray buf; while(!ts.atEnd()) { line = ts.readLine(); if(QRegExp("^END").indexIn(line) != -1) break; line = line.trimmed(); QRegExp rx("\\\\([0-3][0-7][0-7])"); int pos = 0; while((pos = rx.indexIn(line, pos)) != -1) { QString str = rx.capturedTexts()[1]; uchar c = str.toInt(0, 8); buf.append(c); pos += rx.matchedLength(); } } printf(">> [%s], %d bytes\n", qPrintable(name), buf.size()); QTextStream ts(&outfile); ts << "-----BEGIN CERTIFICATE-----" << '\n'; QCA::Base64 enc; enc.setLineBreaksEnabled(true); enc.setLineBreaksColumn(64); ts << enc.arrayToString(buf) << '\n'; ts << "-----END CERTIFICATE-----" << '\n'; ++count; } } printf("Wrote %d certs to [%s]\n", count, argv[2]); return 0; }
bool EncryptedStore::doFinalize() { Q_D(KOdfStore); if (d->good) { if (isOpen()) { close(); } if (d->mode == Write) { // First change the manifest file and write it // We'll use the QDom classes here, since KXmlReader and KXmlWriter have no way of copying a complete xml-file // other than parsing it completely and rebuilding it. // Errorhandling here is done to prevent data from being lost whatever happens // TODO: Convert this to KoXML when KoXML is extended enough // Note: right now this is impossible due to lack of possibilities to copy an element as-is QDomDocument document; if (m_manifestBuffer.isEmpty()) { // No manifest? Better create one document = QDomDocument(); QDomElement rootElement = document.createElement("manifest:manifest"); rootElement.setAttribute("xmlns:manifest", "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"); document.appendChild(rootElement); } if (!m_manifestBuffer.isEmpty() && !document.setContent(m_manifestBuffer)) { // Oi! That's fresh XML we should have here! // This is the only case we can't fix KMessage::message(KMessage::Error, i18n("The manifest file seems to be corrupted. It cannot be modified and the document will remain unreadable. Please try and save the document again to prevent losing your work.")); m_pZip->close(); return false; } QDomElement documentElement = document.documentElement(); QDomNodeList fileElements = documentElement.elementsByTagName("manifest:file-entry"); // Search all files in the manifest QStringList foundFiles; for (int i = 0; i < fileElements.size(); i++) { QDomElement fileElement = fileElements.item(i).toElement(); QString fullpath = fileElement.toElement().attribute("manifest:full-path"); // See if it's encrypted if (fullpath.isEmpty() || !m_encryptionData.contains(fullpath)) { continue; } foundFiles += fullpath; KoEncryptedStore_EncryptionData encData = m_encryptionData.value(fullpath); // Set the unencrypted size of the file fileElement.setAttribute("manifest:size", encData.filesize); // See if the user of this store has already provided (old) encryption data QDomNodeList childElements = fileElement.elementsByTagName("manifest:encryption-data"); QDomElement encryptionElement; QDomElement algorithmElement; QDomElement keyDerivationElement; if (childElements.isEmpty()) { encryptionElement = document.createElement("manifest:encryption-data"); fileElement.appendChild(encryptionElement); } else { encryptionElement = childElements.item(0).toElement(); } childElements = encryptionElement.elementsByTagName("manifest:algorithm"); if (childElements.isEmpty()) { algorithmElement = document.createElement("manifest:algorithm"); encryptionElement.appendChild(algorithmElement); } else { algorithmElement = childElements.item(0).toElement(); } childElements = encryptionElement.elementsByTagName("manifest:key-derivation"); if (childElements.isEmpty()) { keyDerivationElement = document.createElement("manifest:key-derivation"); encryptionElement.appendChild(keyDerivationElement); } else { keyDerivationElement = childElements.item(0).toElement(); } // Set the right encryption data QCA::Base64 encoder; QCA::SecureArray checksum = encoder.encode(encData.checksum); if (encData.checksumShort) { encryptionElement.setAttribute("manifest:checksum-type", "SHA1/1K"); } else { encryptionElement.setAttribute("manifest:checksum-type", "SHA1"); } encryptionElement.setAttribute("manifest:checksum", QString(checksum.toByteArray())); QCA::SecureArray initVector = encoder.encode(encData.initVector); algorithmElement.setAttribute("manifest:algorithm-name", "Blowfish CFB"); algorithmElement.setAttribute("manifest:initialisation-vector", QString(initVector.toByteArray())); QCA::SecureArray salt = encoder.encode(encData.salt); keyDerivationElement.setAttribute("manifest:key-derivation-name", "PBKDF2"); keyDerivationElement.setAttribute("manifest:iteration-count", QString::number(encData.iterationCount)); keyDerivationElement.setAttribute("manifest:salt", QString(salt.toByteArray())); } if (foundFiles.size() < m_encryptionData.size()) { QList<QString> keys = m_encryptionData.keys(); for (int i = 0; i < keys.size(); i++) { if (!foundFiles.contains(keys.value(i))) { KoEncryptedStore_EncryptionData encData = m_encryptionData.value(keys.value(i)); QDomElement fileElement = document.createElement("manifest:file-entry"); fileElement.setAttribute("manifest:full-path", keys.value(i)); fileElement.setAttribute("manifest:size", encData.filesize); fileElement.setAttribute("manifest:media-type", ""); documentElement.appendChild(fileElement); QDomElement encryptionElement = document.createElement("manifest:encryption-data"); QCA::Base64 encoder; QCA::SecureArray checksum = encoder.encode(encData.checksum); QCA::SecureArray initVector = encoder.encode(encData.initVector); QCA::SecureArray salt = encoder.encode(encData.salt); if (encData.checksumShort) { encryptionElement.setAttribute("manifest:checksum-type", "SHA1/1K"); } else { encryptionElement.setAttribute("manifest:checksum-type", "SHA1"); } encryptionElement.setAttribute("manifest:checksum", QString(checksum.toByteArray())); fileElement.appendChild(encryptionElement); QDomElement algorithmElement = document.createElement("manifest:algorithm"); algorithmElement.setAttribute("manifest:algorithm-name", "Blowfish CFB"); algorithmElement.setAttribute("manifest:initialisation-vector", QString(initVector.toByteArray())); encryptionElement.appendChild(algorithmElement); QDomElement keyDerivationElement = document.createElement("manifest:key-derivation"); keyDerivationElement.setAttribute("manifest:key-derivation-name", "PBKDF2"); keyDerivationElement.setAttribute("manifest:iteration-count", QString::number(encData.iterationCount)); keyDerivationElement.setAttribute("manifest:salt", QString(salt.toByteArray())); encryptionElement.appendChild(keyDerivationElement); } } } m_manifestBuffer = document.toByteArray(); m_pZip->setCompression(KZip::DeflateCompression); if (!m_pZip->writeFile(MANIFEST_FILE, "", "", m_manifestBuffer.data(), m_manifestBuffer.size())) { KMessage::message(KMessage::Error, i18n("The manifest file cannot be written. The document will remain unreadable. Please try and save the document again to prevent losing your work.")); m_pZip->close(); return false; } } } if (m_pZip) return m_pZip->close(); else return true; }
int main(int argc, char** argv) { // the Initializer object sets things up, and // also does cleanup when it goes out of scope QCA::Initializer init; QCoreApplication app(argc, argv); // We need to ensure that we have certificate handling support if ( !QCA::isSupported( "cert" ) ) { std::cout << "Sorry, no PKI certificate support" << std::endl; return 1; } // Read in a private key QCA::PrivateKey privKey; QCA::ConvertResult convRes; QCA::SecureArray passPhrase = "start"; privKey = QCA::PrivateKey::fromPEMFile( "Userkey.pem", passPhrase, &convRes ); if ( convRes != QCA::ConvertGood ) { std::cout << "Sorry, could not import Private Key" << std::endl; return 1; } // Read in a matching public key cert // you could also build this using the fromPEMFile() method QCA::Certificate pubCert( "User.pem" ); if ( pubCert.isNull() ) { std::cout << "Sorry, could not import public key certificate" << std::endl; return 1; } // We are building the certificate into a SecureMessageKey object, via a // CertificateChain QCA::SecureMessageKey secMsgKey; QCA::CertificateChain chain; chain += pubCert; secMsgKey.setX509CertificateChain( chain ); // build up a SecureMessage object, based on our public key certificate QCA::CMS cms; QCA::SecureMessage msg(&cms); msg.setRecipient(secMsgKey); // Some plain text - we use the first command line argument if provided QByteArray plainText = (argc >= 2) ? argv[1] : "What do ya want for nuthin'"; // Now use the SecureMessage object to encrypt the plain text. msg.startEncrypt(); msg.update(plainText); msg.end(); // I think it is reasonable to wait for 1 second for this msg.waitForFinished(1000); // check to see if it worked if(!msg.success()) { std::cout << "Error encrypting: " << msg.errorCode() << std::endl; return 1; } // get the result QCA::SecureArray cipherText = msg.read(); QCA::Base64 enc; std::cout << plainText.data() << " encrypts to (in base 64): "; std::cout << qPrintable( enc.arrayToString( cipherText ) ) << std::endl; // Show we can decrypt it with the private key if ( !privKey.canDecrypt() ) { std::cout << "Private key cannot be used to decrypt" << std::endl; return 1; } QCA::SecureArray plainTextResult; if ( 0 == privKey.decrypt(cipherText, &plainTextResult, QCA::EME_PKCS1_OAEP ) ) { std::cout << "Decryption process failed" << std::endl; return 1; } std::cout << qPrintable( enc.arrayToString( cipherText ) ); std::cout << " (in base 64) decrypts to: "; std::cout << plainTextResult.data() << std::endl; return 0; }