mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-22 00:06:12 -05:00
[auth] Add PKCS8 to PKCS1 key conversion for macOS (deps on libtasn1)
See description of QgsAuthCertUtils::pkcs8PrivateKey. This fix may be needed on other platforms (untested at this point), because Qt5 QSslkey class *still* does not directly support creation using non-PKCS1 PEM- or DER-encoded data, though QCA, whose qca-ossl plugin is linked to OpenSSL, does support PKCS1 and PKCS8.
This commit is contained in:
parent
8107f91037
commit
c66de14055
@ -320,6 +320,11 @@ IF(WITH_CORE)
|
||||
FIND_QCAOSSL_PLUGIN_CPP(ENABLE_TESTS)
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
IF (APPLE)
|
||||
# Libtasn1 is for DER-encoded PKI ASN.1 parsing/extracting workarounds
|
||||
FIND_PACKAGE(Libtasn1 REQUIRED)
|
||||
ENDIF (APPLE)
|
||||
|
||||
IF (SUPPRESS_QT_WARNINGS)
|
||||
# Newer versions of UseQt4.cmake include Qt with -isystem automatically
|
||||
# This can be used to force this behavior on older systems
|
||||
|
45
cmake/FindLibtasn1.cmake
Normal file
45
cmake/FindLibtasn1.cmake
Normal file
@ -0,0 +1,45 @@
|
||||
# Find Libtasn1
|
||||
# ~~~~~~~~~~~~~~~
|
||||
# CMake module to search for Libtasn1 ASN.1 library and header(s) from:
|
||||
# https://www.gnu.org/software/libtasn1/
|
||||
#
|
||||
# If it's found it sets LIBTASN1_FOUND to TRUE
|
||||
# and following variables are set:
|
||||
# LIBTASN1_INCLUDE_DIR
|
||||
# LIBTASN1_LIBRARY
|
||||
#
|
||||
# Copyright (c) 2017, Boundless Spatial
|
||||
# Author: Larry Shaffer <lshaffer (at) boundlessgeo (dot) com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
find_path(LIBTASN1_INCLUDE_DIR
|
||||
NAMES libtasn1.h
|
||||
PATHS
|
||||
${LIB_DIR}/include
|
||||
"$ENV{LIB_DIR}/include"
|
||||
$ENV{INCLUDE}
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
find_library(LIBTASN1_LIBRARY
|
||||
NAMES tasn1
|
||||
PATHS
|
||||
${LIB_DIR}
|
||||
"$ENV{LIB_DIR}"
|
||||
$ENV{LIB}
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
Libtasn1
|
||||
REQUIRED_VARS LIBTASN1_INCLUDE_DIR LIBTASN1_LIBRARY
|
||||
FOUND_VAR LIBTASN1_FOUND
|
||||
)
|
||||
|
||||
mark_as_advanced(LIBTASN1_INCLUDE_DIR LIBTASN1_LIBRARY)
|
@ -9,3 +9,9 @@ INSTALL(DIRECTORY data DESTINATION ${QGIS_DATA_DIR}/resources)
|
||||
IF (WITH_SERVER)
|
||||
INSTALL(DIRECTORY server DESTINATION ${QGIS_DATA_DIR}/resources)
|
||||
ENDIF (WITH_SERVER)
|
||||
|
||||
IF (APPLE)
|
||||
# ASN.1 definition files of PKIX elements
|
||||
INSTALL(FILES pkcs8.asn
|
||||
DESTINATION ${QGIS_DATA_DIR}/resources)
|
||||
ENDIF (APPLE)
|
||||
|
63
resources/pkcs8.asn
Normal file
63
resources/pkcs8.asn
Normal file
@ -0,0 +1,63 @@
|
||||
PKCS-8 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-8(8)
|
||||
modules(1) pkcs-8(1)}
|
||||
|
||||
-- $Revision: 1.5 $
|
||||
|
||||
-- This module has been checked for conformance with the ASN.1
|
||||
-- standard by the OSS ASN.1 Tools
|
||||
|
||||
DEFINITIONS EXPLICIT TAGS ::=
|
||||
|
||||
BEGIN
|
||||
|
||||
-- EXPORTS All --
|
||||
-- All types and values defined in this module is exported for use in
|
||||
-- other ASN.1 modules.
|
||||
|
||||
-- attribute data types --
|
||||
|
||||
Attribute ::= SEQUENCE {
|
||||
type AttributeType,
|
||||
values SET OF AttributeValue
|
||||
-- at least one value is required --
|
||||
}
|
||||
|
||||
AttributeType ::= OBJECT IDENTIFIER
|
||||
|
||||
AttributeValue ::= ANY DEFINED BY type
|
||||
|
||||
AttributeTypeAndValue ::= SEQUENCE {
|
||||
type AttributeType,
|
||||
value AttributeValue }
|
||||
|
||||
AlgorithmIdentifier ::= SEQUENCE {
|
||||
algorithm OBJECT IDENTIFIER,
|
||||
parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
-- contains a value of the type
|
||||
-- registered for use with the
|
||||
-- algorithm object identifier value
|
||||
|
||||
-- Private-key information syntax
|
||||
|
||||
PrivateKeyInfo ::= SEQUENCE {
|
||||
version Version,
|
||||
privateKeyAlgorithm AlgorithmIdentifier,
|
||||
privateKey PrivateKey,
|
||||
attributes [0] Attributes OPTIONAL }
|
||||
|
||||
Version ::= INTEGER {v1(0)}
|
||||
|
||||
PrivateKey ::= OCTET STRING
|
||||
|
||||
Attributes ::= SET OF Attribute
|
||||
|
||||
-- Encrypted private-key information syntax
|
||||
|
||||
EncryptedPrivateKeyInfo ::= SEQUENCE {
|
||||
encryptionAlgorithm AlgorithmIdentifier,
|
||||
encryptedData EncryptedData
|
||||
}
|
||||
|
||||
EncryptedData ::= OCTET STRING
|
||||
|
||||
END
|
@ -1179,6 +1179,13 @@ INCLUDE_DIRECTORIES(SYSTEM
|
||||
${QTKEYCHAIN_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
IF (APPLE)
|
||||
# Libtasn1 is for DER-encoded PKI ASN.1 parsing/extracting workarounds
|
||||
INCLUDE_DIRECTORIES(SYSTEM
|
||||
${LIBTASN1_INCLUDE_DIR}
|
||||
)
|
||||
ENDIF (APPLE)
|
||||
|
||||
|
||||
#for PAL classes
|
||||
IF (WIN32)
|
||||
@ -1249,7 +1256,7 @@ IF (WIN32)
|
||||
ENDIF (WIN32)
|
||||
|
||||
IF (APPLE)
|
||||
TARGET_LINK_LIBRARIES(qgis_core qgis_native)
|
||||
TARGET_LINK_LIBRARIES(qgis_core qgis_native ${LIBTASN1_LIBRARY})
|
||||
ENDIF (APPLE)
|
||||
|
||||
IF (NOT WITH_INTERNAL_QEXTSERIALPORT)
|
||||
|
@ -23,9 +23,16 @@
|
||||
#include <QSslCertificate>
|
||||
#include <QUuid>
|
||||
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsauthmanager.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <string.h>
|
||||
#include "libtasn1.h"
|
||||
#endif
|
||||
|
||||
|
||||
QString QgsAuthCertUtils::getSslProtocolName( QSsl::SslProtocol protocol )
|
||||
{
|
||||
switch ( protocol )
|
||||
@ -273,37 +280,242 @@ bool QgsAuthCertUtils::pemIsPkcs8( const QString &keyPemTxt )
|
||||
return keyPemTxt.contains( pkcs8Header ) && keyPemTxt.contains( pkcs8Footer );
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QByteArray QgsAuthCertUtils::pkcs8PrivateKey( QByteArray &pkcs8Der )
|
||||
{
|
||||
QByteArray pkcs1;
|
||||
|
||||
if ( pkcs8Der.isEmpty() )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, passed DER is empty" ) );
|
||||
return pkcs1;
|
||||
}
|
||||
// Dump as unarmored PEM format, e.g. missing '-----BEGIN|END...' wrapper
|
||||
//QgsDebugMsg ( QStringLiteral( "pkcs8Der: %1" ).arg( QString( pkcs8Der.toBase64() ) ) );
|
||||
|
||||
QFileInfo asnDefsRsrc( QgsApplication::pkgDataPath() + QStringLiteral( "/resources/pkcs8.asn" ) );
|
||||
if ( ! asnDefsRsrc.exists() )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, pkcs.asn resource file not found: %1" ).arg( asnDefsRsrc.filePath() ) );
|
||||
return pkcs1;
|
||||
}
|
||||
const char *asnDefsFile = asnDefsRsrc.absoluteFilePath().toLocal8Bit().constData();
|
||||
|
||||
int asn1_result = ASN1_SUCCESS, der_len = 0, oct_len = 0;
|
||||
asn1_node definitions = NULL, structure = NULL;
|
||||
char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE], oct_data[1024];
|
||||
unsigned char *der = NULL;
|
||||
unsigned int flags = 0; //TODO: see if any or all ASN1_DECODE_FLAG_* flags can be set
|
||||
unsigned oct_etype;
|
||||
|
||||
// Base PKCS#8 element to decode
|
||||
QString typeName( QStringLiteral( "PKCS-8.PrivateKeyInfo" ) );
|
||||
|
||||
asn1_result = asn1_parser2tree( asnDefsFile, &definitions, errorDescription );
|
||||
|
||||
switch ( asn1_result )
|
||||
{
|
||||
case ASN1_SUCCESS:
|
||||
QgsDebugMsgLevel( QStringLiteral( "Parse: done.\n" ), 4 );
|
||||
break;
|
||||
case ASN1_FILE_NOT_FOUND:
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, file not found: %1" ).arg( asnDefsFile ) );
|
||||
return pkcs1;
|
||||
case ASN1_SYNTAX_ERROR:
|
||||
case ASN1_IDENTIFIER_NOT_FOUND:
|
||||
case ASN1_NAME_TOO_LONG:
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 parsing: %1" ).arg( errorDescription ) );
|
||||
return pkcs1;
|
||||
default:
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, libtasn1: %1" ).arg( asn1_strerror( asn1_result ) ) );
|
||||
return pkcs1;
|
||||
}
|
||||
|
||||
// Generate the ASN.1 structure
|
||||
asn1_result = asn1_create_element( definitions, typeName.toLatin1().constData(), &structure );
|
||||
|
||||
//asn1_print_structure( stdout, structure, "", ASN1_PRINT_ALL);
|
||||
|
||||
if ( asn1_result != ASN1_SUCCESS )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, structure creation: %1" ).arg( asn1_strerror( asn1_result ) ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
// Populate the ASN.1 structure with decoded DER data
|
||||
der = reinterpret_cast<unsigned char *>( pkcs8Der.data() );
|
||||
der_len = pkcs8Der.size();
|
||||
|
||||
if ( flags != 0 )
|
||||
{
|
||||
asn1_result = asn1_der_decoding2( &structure, der, &der_len, flags, errorDescription );
|
||||
}
|
||||
else
|
||||
{
|
||||
asn1_result = asn1_der_decoding( &structure, der, der_len, errorDescription );
|
||||
}
|
||||
|
||||
if ( asn1_result != ASN1_SUCCESS )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, decoding: %1" ).arg( errorDescription ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "Decoding: %1" ).arg( asn1_strerror( asn1_result ) ), 4 );
|
||||
}
|
||||
|
||||
if ( QgsLogger::debugLevel() >= 4 )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "DECODING RESULT:" ) );
|
||||
asn1_print_structure( stdout, structure, "", ASN1_PRINT_NAME_TYPE_VALUE );
|
||||
}
|
||||
|
||||
// Validate and extract privateKey value
|
||||
QgsDebugMsgLevel( QStringLiteral( "Validating privateKey type..." ), 4 );
|
||||
typeName.append( QStringLiteral( ".privateKey" ) );
|
||||
QgsDebugMsgLevel( QStringLiteral( "privateKey element name: %1" ).arg( typeName ), 4 );
|
||||
|
||||
asn1_result = asn1_read_value_type( structure, "privateKey", NULL, &oct_len, &oct_etype );
|
||||
|
||||
if ( asn1_result != ASN1_MEM_ERROR ) // not sure why ASN1_MEM_ERROR = success, but it does
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 read privateKey value type: %1" ).arg( asn1_strerror( asn1_result ) ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
if ( oct_etype != ASN1_ETYPE_OCTET_STRING )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 privateKey value not octet string, but type: %1" ).arg( static_cast<int>( oct_etype ) ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
if ( oct_len == 0 )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 privateKey octet string empty" ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
QgsDebugMsgLevel( QStringLiteral( "Reading privateKey value..." ), 4 );
|
||||
asn1_result = asn1_read_value( structure, "privateKey", oct_data, &oct_len );
|
||||
|
||||
if ( asn1_result != ASN1_SUCCESS )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 read privateKey value: %1" ).arg( asn1_strerror( asn1_result ) ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
if ( oct_len == 0 )
|
||||
{
|
||||
QgsDebugMsg( QStringLiteral( "ERROR, asn1 privateKey value octet string empty" ) );
|
||||
goto PKCS1DONE;
|
||||
}
|
||||
|
||||
pkcs1 = QByteArray( oct_data, oct_len );
|
||||
|
||||
// !!! SENSITIVE DATA !!!
|
||||
QgsDebugMsgLevel( QStringLiteral( "privateKey octet data as PEM: %1" ).arg( QString( pkcs1.toBase64() ) ), 9 );
|
||||
|
||||
PKCS1DONE:
|
||||
|
||||
asn1_delete_structure( &structure );
|
||||
return pkcs1;
|
||||
}
|
||||
#endif
|
||||
|
||||
QStringList QgsAuthCertUtils::pkcs12BundleToPem( const QString &bundlepath,
|
||||
const QString &bundlepass,
|
||||
bool reencrypt )
|
||||
{
|
||||
QStringList empty;
|
||||
if ( !QCA::isSupported( "pkcs12" ) )
|
||||
{
|
||||
QgsDebugMsg( QString( "QCA does not support PKCS#12" ) );
|
||||
return empty;
|
||||
}
|
||||
|
||||
QCA::KeyBundle bundle( QgsAuthCertUtils::qcaKeyBundle( bundlepath, bundlepass ) );
|
||||
if ( bundle.isNull() )
|
||||
{
|
||||
QgsDebugMsg( QString( "FAILED to convert PKCS#12 file to QCA key bundle: %1" ).arg( bundlepath ) );
|
||||
return empty;
|
||||
}
|
||||
|
||||
QCA::SecureArray passarray;
|
||||
if ( reencrypt && !bundlepass.isEmpty() )
|
||||
{
|
||||
passarray = QCA::SecureArray( bundlepass.toUtf8() );
|
||||
}
|
||||
|
||||
QString algtype;
|
||||
QSsl::KeyAlgorithm keyalg = QSsl::Opaque;
|
||||
if ( bundle.privateKey().isRSA() )
|
||||
{
|
||||
algtype = QStringLiteral( "rsa" );
|
||||
keyalg = QSsl::Rsa;
|
||||
}
|
||||
else if ( bundle.privateKey().isDSA() )
|
||||
{
|
||||
algtype = QStringLiteral( "dsa" );
|
||||
keyalg = QSsl::Dsa;
|
||||
}
|
||||
else if ( bundle.privateKey().isDH() )
|
||||
{
|
||||
algtype = QStringLiteral( "dh" );
|
||||
}
|
||||
// TODO: add support for EC keys, once QCA supports them
|
||||
|
||||
return QStringList() << bundle.certificateChain().primary().toPEM() << bundle.privateKey().toPEM( passarray ) << algtype;
|
||||
// can currently only support RSA and DSA between QCA and Qt
|
||||
if ( keyalg == QSsl::Opaque )
|
||||
{
|
||||
QgsDebugMsg( QString( "FAILED to read PKCS#12 key (only RSA and DSA algorithms supported): %1" ).arg( bundlepath ) );
|
||||
return empty;
|
||||
}
|
||||
|
||||
QString keyPem;
|
||||
#ifdef Q_OS_MAC
|
||||
if ( keyalg == QSsl::Rsa && QgsAuthCertUtils::pemIsPkcs8( bundle.privateKey().toPEM() ) )
|
||||
{
|
||||
QgsDebugMsgLevel( QString( "Private key is PKCS#8: attempting conversion to PKCS#1..." ), 4 );
|
||||
// if RSA, convert from PKCS#8 key to 'traditional' OpenSSL RSA format, which Qt prefers
|
||||
// note: QCA uses OpenSSL, regardless of the Qt SSL backend, and 1.0.2+ OpenSSL versions return
|
||||
// RSA private keys as PKCS#8, which choke Qt upon QSslKey creation
|
||||
|
||||
QByteArray pkcs8Der = bundle.privateKey().toDER().toByteArray();
|
||||
if ( pkcs8Der.isEmpty() )
|
||||
{
|
||||
QgsDebugMsg( QString( "FAILED to convert PKCS#12 key to DER-encoded format: %1" ).arg( bundlepath ) );
|
||||
return empty;
|
||||
}
|
||||
|
||||
QByteArray pkcs1Der = QgsAuthCertUtils::pkcs8PrivateKey( pkcs8Der );
|
||||
if ( pkcs1Der.isEmpty() )
|
||||
{
|
||||
QgsDebugMsg( QString( "FAILED to convert PKCS#12 key from PKCS#8 to PKCS#1: %1" ).arg( bundlepath ) );
|
||||
return empty;
|
||||
}
|
||||
|
||||
QSslKey pkcs1Key( pkcs1Der, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey );
|
||||
if ( pkcs1Key.isNull() )
|
||||
{
|
||||
QgsDebugMsg( QString( "FAILED to convert PKCS#12 key from PKCS#8 to PKCS#1 QSslKey: %1" ).arg( bundlepath ) );
|
||||
return empty;
|
||||
}
|
||||
keyPem = QString( pkcs1Key.toPem( passarray.toByteArray() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
keyPem = bundle.privateKey().toPEM( passarray );
|
||||
}
|
||||
#else
|
||||
keyPem = bundle.privateKey().toPEM( passarray );
|
||||
#endif
|
||||
|
||||
QgsDebugMsgLevel( QString( "PKCS#12 cert as PEM:\n%1" ).arg( QString( bundle.certificateChain().primary().toPEM() ) ), 4 );
|
||||
// !!! SENSITIVE DATA !!!
|
||||
QgsDebugMsgLevel( QString( "PKCS#12 key as PEM:\n%1" ).arg( QString( keyPem ) ), 9 );
|
||||
|
||||
return QStringList() << bundle.certificateChain().primary().toPEM() << keyPem << algtype;
|
||||
}
|
||||
|
||||
QList<QSslCertificate> QgsAuthCertUtils::pkcs12BundleCas( const QString &bundlepath, const QString &bundlepass )
|
||||
|
@ -171,6 +171,25 @@ class CORE_EXPORT QgsAuthCertUtils
|
||||
*/
|
||||
static bool pemIsPkcs8( const QString &keyPemTxt );
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
/**
|
||||
* Extract the PrivateKey ASN.1 element of a DER-encoded PKCS#8 private key
|
||||
* \param pkcs8Der PKCS#8 DER-encoded private key data
|
||||
* \returns DER-encoded private key on success or an empty QByteArray upon failure
|
||||
* \note On some platforms, e.g. macOS, where the default SSL backend is not OpenSSL, a QSslKey
|
||||
* can not be created using PKCS#8-formatted data. However, PKCS#8 private key ASN.1 structures
|
||||
* contain the key data inside a wrapper describing the algorithm used, e.g. RSA, DSA, ECC etc.
|
||||
* Extracted PrivateKey ASN.1 data can be used to create a compatible QSslKey,
|
||||
* e.g. 'traditional' SSLeay RSA-specific PKCS#1.
|
||||
* By default OpenSSL 1.0.0+ returns private keys as PKCS#8, previously it was PKCS#1.
|
||||
* \note This function requires 'libtasn1' development files and library, which is used
|
||||
* to parse and extract the PrivateKey element from an ASN.1 PKCS#8 structure.
|
||||
*/
|
||||
static QByteArray pkcs8PrivateKey( QByteArray &pkcs8Der ) SIP_SKIP;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Return list of certificate, private key and algorithm (as PEM text) for a PKCS#12 bundle
|
||||
* \param bundlepath File path to the PKCS bundle
|
||||
* \param bundlepass Passphrase for bundle
|
||||
|
@ -72,6 +72,63 @@ void TestQgsAuthCertUtils::testPkcsUtils()
|
||||
pkcs = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key-pkcs8-rsa.pem", false );
|
||||
QVERIFY( !pkcs.isEmpty() );
|
||||
QVERIFY( QgsAuthCertUtils::pemIsPkcs8( QString( pkcs ) ) );
|
||||
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QByteArray pkcs1;
|
||||
pkcs.clear();
|
||||
|
||||
// Nothing should return nothing
|
||||
pkcs1 = QgsAuthCertUtils::pkcs8PrivateKey( pkcs );
|
||||
QVERIFY( pkcs1.isEmpty() );
|
||||
|
||||
pkcs.clear();
|
||||
pkcs1.clear();
|
||||
// Is actually a PKCS#1 key, not #8
|
||||
pkcs = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key.der", false );
|
||||
QVERIFY( !pkcs.isEmpty() );
|
||||
pkcs1 = QgsAuthCertUtils::pkcs8PrivateKey( pkcs );
|
||||
QVERIFY( pkcs1.isEmpty() );
|
||||
|
||||
pkcs.clear();
|
||||
pkcs1.clear();
|
||||
// Is PKCS#1 PEM text, not DER
|
||||
pkcs = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key.pem", false );
|
||||
QVERIFY( !pkcs.isEmpty() );
|
||||
pkcs1 = QgsAuthCertUtils::pkcs8PrivateKey( pkcs );
|
||||
QVERIFY( pkcs1.isEmpty() );
|
||||
|
||||
pkcs.clear();
|
||||
pkcs1.clear();
|
||||
// Is PKCS#8 PEM text, not DER
|
||||
pkcs = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key-pkcs8-rsa.pem", false );
|
||||
QVERIFY( !pkcs.isEmpty() );
|
||||
pkcs1 = QgsAuthCertUtils::pkcs8PrivateKey( pkcs );
|
||||
QVERIFY( pkcs1.isEmpty() );
|
||||
|
||||
pkcs.clear();
|
||||
pkcs1.clear();
|
||||
// Correct PKCS#8 DER input
|
||||
pkcs = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key-pkcs8-rsa.der", false );
|
||||
QVERIFY( !pkcs.isEmpty() );
|
||||
pkcs1 = QgsAuthCertUtils::pkcs8PrivateKey( pkcs );
|
||||
QVERIFY( !pkcs1.isEmpty() );
|
||||
|
||||
// PKCS#8 DER format should fail, and the reason for QgsAuthCertUtils::pkcs8PrivateKey
|
||||
// (as of Qt5.9.0, and where macOS Qt5 SSL backend is not OpenSSL, and
|
||||
// where PKCS#8 is *still* unsupported for macOS)
|
||||
QSslKey pkcs8Key( pkcs, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey );
|
||||
QVERIFY( pkcs8Key.isNull() );
|
||||
|
||||
// PKCS#1 DER format should work
|
||||
QSslKey pkcs1Key( pkcs1, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey );
|
||||
QVERIFY( !pkcs1Key.isNull() );
|
||||
|
||||
// Converted PKCS#8 DER should match PKCS#1 PEM
|
||||
QByteArray pkcs1PemRef = QgsAuthCertUtils::fileData( sPkiData + "/gerardus_key.pem", true );
|
||||
QVERIFY( !pkcs1PemRef.isEmpty() );
|
||||
QCOMPARE( pkcs1Key.toPem(), pkcs1PemRef );
|
||||
#endif
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsAuthCertUtils )
|
||||
|
BIN
tests/testdata/auth_system/certs_keys/fra_key-pkcs8-rsa.der
vendored
Normal file
BIN
tests/testdata/auth_system/certs_keys/fra_key-pkcs8-rsa.der
vendored
Normal file
Binary file not shown.
16
tests/testdata/auth_system/certs_keys/fra_key-pkcs8-rsa.pem
vendored
Normal file
16
tests/testdata/auth_system/certs_keys/fra_key-pkcs8-rsa.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOOA/yLAj0TOL6Z3
|
||||
OGY+2JxaSmStwl5veQjp+VoAOoxDVjQDOxuBNihZ1gGUVPc2cQm8HS+nMizw9SiC
|
||||
l0ZiP23QqkL9Xgd1+scE1Hhxf8cvTp2Ek3QKbKlfol3wGZgGElwkrVed77+l7PjX
|
||||
VxLd2UbnZEF8TURntOyMKeYwi53vAgMBAAECgYA9/tIH41dnVZSQlV5uJmQav1QU
|
||||
eXFFELV342KKzxMlU9gy1kqOJTjf6BM0XPqGX3SQRY3ihXpb2tHD10pn6LAFtiOR
|
||||
ymfPJ+fs3TiPUn+Ut7TkedKkTxu5IT5C5Nu0FllcTo9mpi5ytfu6D+gkrB8fX/fZ
|
||||
5+jGdevrd9WWU+v5wQJBAP8AerrTiFLCJRocP/jIdwg+gmEdcPYg5cmeNVpAUuAN
|
||||
CSa5QYIQ9xB3ERUVo4ODCEGQFdYDZaPPvGp5wICo9U8CQQDkZPaaj4UegQZp/Vkf
|
||||
7fQBmRzVhccxewV/HlEqJR1iQydjN3SfTU3cI0QmZL805emSN0f2sgT4lV4tdLbJ
|
||||
ueVhAkEAk2C+jf21u0bz1IxhOLL7gKtIBULTx5yp0gX7BedJPq6qDFRjlP2jHUQD
|
||||
fnEcKOTxP5s7043xD2T/m3Y0mOeNpwJAaFDI5Y05otYRhOVnCJNZSEWTit7APRRQ
|
||||
TWAeeB5djlzXp5RTmtLnBe3BmbuYLWP5S4QeRUnHxXYLfr15IyfZ4QJBAMxGWwet
|
||||
yoR03gyOwSagP53hcV5wGWu1ThKlmzrLl6ulJYb/3lwbYeNCaI5ZzGaSiycWC/8K
|
||||
9zIREiwz1u/iupk=
|
||||
-----END PRIVATE KEY-----
|
BIN
tests/testdata/auth_system/certs_keys/gerardus_key-pkcs8-rsa.der
vendored
Normal file
BIN
tests/testdata/auth_system/certs_keys/gerardus_key-pkcs8-rsa.der
vendored
Normal file
Binary file not shown.
16
tests/testdata/auth_system/certs_keys/gerardus_key-pkcs8-rsa.pem
vendored
Normal file
16
tests/testdata/auth_system/certs_keys/gerardus_key-pkcs8-rsa.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALrXW9BbnHSp96kA
|
||||
naNMFr7Wu4xUd0HwPiLmkSpriRqSMI9EQF6+Bib50BIHYGpmAXdsH44FoD8k2r9q
|
||||
C5sjiJpQY7pba3IB/n0pGufQJe4rw2lKWBKvl3ADjVoqPfCBT5mnpyEppDmXxOJr
|
||||
ANH+ojsnjZh44fkq6emgEfganGcrAgMBAAECgYEAuO2jQG0MRCRernWfkRskgCrF
|
||||
YrXPfAIvXhfboqLhBt2fFo41MBDgwf8MRGvssCLaXLs12DoVS6pMoJxzdFANSQyl
|
||||
Oqf2wLtiTMzjPslv7x8R2ho/0uLxeccP5xHpLSxypbcXF3PzCxp4gNpnZWDvwx9V
|
||||
Ofgrsjx//toTiMcSYiECQQDurSJmr+wDoBblptvFbO8KrfnkvMlTlQqeYQXmceGg
|
||||
Mdxcygm3nqAw/Tiqd5LUGLgQP3R/Sot8ZjSPtLme6ilTAkEAyGcSiFhx/eIYwWmp
|
||||
L1AJ4DSp9MQI3nVxxwrKWwyq48zxrDcSZcUJYFMphgfgzTwupTMoDNwxPiNdkUxN
|
||||
SdaXyQJAIUSyydt1q1+yMVqbwZ4Yh8WOUoraCTN6Im9lsiRnjbvFeo2S4yxSKeHx
|
||||
9xjpt3Smm2Us6N1MKg/Y/br0MKl1DwJBAIIGrnWcvUl3G4zSm51BF0dLpEJVt1Nv
|
||||
bEUy8RymWXK4lM2iZeN2NqEzFCwMjIVdWP6C9KdzbtfcZmdR1IvmGlECQQDDzyIT
|
||||
6g6z5IxBF1zQJAct34UZyLR+gjcTnT4CAjensHbpEbUvBuKT4D8S+No643rCwRQz
|
||||
mgvgSjp6glQuamby
|
||||
-----END PRIVATE KEY-----
|
BIN
tests/testdata/auth_system/certs_keys/nicholas_key-pkcs8-rsa.der
vendored
Normal file
BIN
tests/testdata/auth_system/certs_keys/nicholas_key-pkcs8-rsa.der
vendored
Normal file
Binary file not shown.
16
tests/testdata/auth_system/certs_keys/nicholas_key-pkcs8-rsa.pem
vendored
Normal file
16
tests/testdata/auth_system/certs_keys/nicholas_key-pkcs8-rsa.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMuZd8GDiWvpMU7W
|
||||
LJBSeDL/bXzdbnmL35RmF+gDOQOS5zZFFz6Nn2PD6xPJxPTSzG46BLjeXdvZVsNN
|
||||
nx8JvLZ4XdehXGdue9C8iHTeNS5di/E9rwBYRaHK9D8NUN54xQLs7SL4v5Y//x3/
|
||||
1p2pRWzhMsJm4o4xi2A0pi4qQmthAgMBAAECgYBIMrvM26A3rBHYKwrSguws6Xch
|
||||
+EPcxkUakrmXhM0K/2UOUaHUhNQoxKjv83TsfHQSAnD6PaB6/a9Owo/SqdlJGXv3
|
||||
f+lvsHx283/PCD/fO/P0NE6L/9S0yYKbYd5r1PvbWBM66+AKS/1u6GevIp9UCpOJ
|
||||
f7P3xwTOcNSIPgP2AQJBAO9vyckXBNcmtASzOUikQk+K4qyQEqzysS1HpuLt7y/w
|
||||
r75BB2sM8h7cXimYIlSPTbPrcMXzoA0rB6iHrhq1sIkCQQDZrwjd/SC9y/9fi+LB
|
||||
MxNnai/f9h+nQzP2VWLNIakDIHXcHaqWp2GjvQW+M6XH/pMJ8g7iFbXi2YtVL2iA
|
||||
6z4ZAkAvXfkYXAJsIc75Iw+RDFXF8J7ZLoNTTYu5fnRIbnOkE0RhKfIyvlPjwQqr
|
||||
xdn8yoC/uDMOJh0incGdGIJb7FepAkB18c2XIdB8paw/Y7a/wWHRFYrNCTkLUnE0
|
||||
Ff2LcaJ2jD7vva8xI43WvtL+xFMdsoSOzfVccDD1sbM5u48e0tb5AkA24I2q6BE8
|
||||
dkW3irynMHLu2y19C6k/QeZRExix8dEpLJh0MRPwtIqeijMav+YSzHLO2h7sHhB3
|
||||
LDQWscGKrSRu
|
||||
-----END PRIVATE KEY-----
|
BIN
tests/testdata/auth_system/certs_keys/ptolemy_key-pkcs8-rsa.der
vendored
Normal file
BIN
tests/testdata/auth_system/certs_keys/ptolemy_key-pkcs8-rsa.der
vendored
Normal file
Binary file not shown.
16
tests/testdata/auth_system/certs_keys/ptolemy_key-pkcs8-rsa.pem
vendored
Normal file
16
tests/testdata/auth_system/certs_keys/ptolemy_key-pkcs8-rsa.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK7KI7uoxRgWQ4AI
|
||||
dAqsGao/M1Mg0C8poMQuv4k2ORplioPLlna5fTlhBFZBiB9f86QLoonwS0iEwhs3
|
||||
5VdJtlvEorjud7HmQesU6SWk7bNBQTdWbJPJgM48ivIjZSjVvBj3zEDJL5u948uJ
|
||||
67zP1gQ5qqOrXDCV5KpXGOkRDDubAgMBAAECgYAgNQcYkSSgJ5oQgX5AaS3hfPvM
|
||||
GYPC7Py+qY6JjgA/qO45Es6K2esFI6dU7YZToa6XT72HhUuZ9Tx/H3GW//Il8MJh
|
||||
WEmiy6hB+yX3yEgq+CuUCgxnZd6BhX6H3O4dRBFxHaTEUjQJpZWrIS0vAzbdgJuM
|
||||
vDbNDYuYgF/ZAMwGYQJBANbxDJzrYQxIelamwiEO9uPGvOoHRopLoIaFZPneSnpp
|
||||
kIyLoCqikAjQuqeqVEOFXlYFfR8wVT9aq/RXqaw0A00CQQDQLZnGwhiaptBn8BL+
|
||||
6RjJM1Rmc1jmjiSNkp+ow573ttJhdgHnC0+CjOcwQu5Db2nzDkT+kkOLm5aCzOuZ
|
||||
/XaHAkEAgAUOWCAxq1k31Ih6M6pwDnZ+an1u3EvzDmxBGjn17jcV6z/2Y65zT2zS
|
||||
364phhXXfDDEt2DYRWXB6USVQIWyOQJAdEkEnQHOvJRx1Z1E/x81uS3y90d3YVIF
|
||||
GQ/OH3cmVTjKS6afaW/n+gS7HzpD3Wdex2YxJAKPuGwwpt/QuzPaAQJAGP8nj5g9
|
||||
oYxzD+x018fxSf/BsTjXU2S6SrbIg5D4B5s5kYFXOvLUS4rfjGWxssyHdtZuFf7T
|
||||
VMmSp5bTS7YAfQ==
|
||||
-----END PRIVATE KEY-----
|
Loading…
x
Reference in New Issue
Block a user