1
0
mirror of https://github.com/mtrojnar/osslsigncode.git synced 2025-04-08 18:28:05 -05:00

Compare commits

...

27 Commits
2.9 ... master

Author SHA1 Message Date
olszomal
4568c890cc Fixed resource leaks, CID 1639164, 1639165, 1639167, 1639168, 1639169 2025-03-31 13:19:35 +02:00
olszomal
4bd167a8be Fixed directly dereferencing parameter p7, CID 1576008 2025-03-31 13:19:35 +02:00
olszomal
e7405fa839 Simplify error handling in PKCS#7 certificate loading, CID 1639170 2025-03-31 13:19:35 +02:00
olszomal
776e2ec7b6 Fix memory management for ministream and difat in MSI output, CID 1639166 2025-03-31 13:19:35 +02:00
olszomal
838aaaee8d libp11 PKCS#11 provider support 2025-03-28 14:05:12 +01:00
olszomal
e8f19a6efe Added verbose output for digest encryption algorithm and signature during verification 2024-12-31 13:53:46 +01:00
olszomal
3a8e25e5bb Added support for multiple OID types in signer info attribute 2024-12-17 17:27:50 +01:00
olszomal
7d1b460dfe Style updates 2024-12-06 22:19:00 +01:00
olszomal
bc3e9e2172 Disable environment updates for Python setup 2024-12-06 22:19:00 +01:00
olszomal
21bce757ef Remove specific CMake version setup for macOS 2024-12-06 22:19:00 +01:00
olszomal
6a43f62835 Remove Python3_EXECUTABLE 2024-12-06 22:19:00 +01:00
olszomal
8780e6f8e4 Fixed pip install 2024-12-06 22:19:00 +01:00
olszomal
78a23caa54 Retain needrestart package in Linux dependency installation 2024-12-06 22:19:00 +01:00
olszomal
d92927aff4 Switch to venv on Linux 2024-12-06 22:19:00 +01:00
olszomal
4f412b5989 Removed VIRTUAL_ENV 2024-12-06 22:19:00 +01:00
olszomal
e6f3ff631d Switch to venv on Windows 2024-12-06 22:19:00 +01:00
olszomal
09135aabb8 Check Python and cryptography version in Windows CI workflow 2024-12-06 22:19:00 +01:00
olszomal
de983e680f Configured macOS environment for arm64 architecture 2024-12-06 22:19:00 +01:00
Michał Trojnara
dc827b94e5 Switch to venv on macOS 2024-12-06 22:19:00 +01:00
olszomal
40ce811701 Fixed conditional compilation for CURL and proxy support 2024-10-25 17:48:01 +02:00
Małgorzata Olszówka
db5b4c4dc0
Add the "-engineCtrl" option to control hardware and CNG engines ()
Documentation updated for CNG engine 1.1 compatibility.
2024-09-08 19:23:38 +02:00
olszomal
4ee429792d Refactor imports to use explicit submodule imports and organize class/function imports 2024-09-06 11:58:28 +02:00
Michał Trojnara
27686c0b0c Missing part of 4dd836bab1832b8a87331f2e73356cda4f01e998 2024-09-05 11:43:25 +02:00
olszomal
21133f9c3b Added the '-blobFile' option to specify a file containing the blob content 2024-09-04 17:51:35 +02:00
Petr Vaněk
64305d6415 tests: add import for python-cryptography >= 43.0.0
write_pkcs12_container method raises following error message with
python-cryptography-43.0.0:

  Error: module 'cryptography.hazmat.primitives.serialization' has no attribute 'pkcs12'

Explicit import of the pkcs12 module resolves the issue.
2024-09-02 13:05:55 +02:00
Michał Trojnara
4dd836bab1 Initial 2.10-dev commit 2024-06-29 21:58:55 +02:00
Michał Trojnara
f57c213207 Use the installed version of Python 2024-06-29 20:52:55 +02:00
12 changed files with 871 additions and 518 deletions

@ -7,7 +7,7 @@ on:
env: env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release BUILD_TYPE: Release
version: osslsigncode-2.9 version: osslsigncode-2.10-dev
jobs: jobs:
build: build:
@ -34,7 +34,7 @@ jobs:
generator: Unix Makefiles generator: Unix Makefiles
vcpkg_root: vcpkg_root:
- id: macOS - id: macOS
triplet: x64-osx triplet: arm64-osx
compiler: clang compiler: clang
os: macOS-latest os: macOS-latest
generator: Unix Makefiles generator: Unix Makefiles
@ -107,17 +107,23 @@ jobs:
if: matrix.compiler == 'mingw' if: matrix.compiler == 'mingw'
run: echo "D:/a/_temp/msys64/mingw64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append run: echo "D:/a/_temp/msys64/mingw64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install apt dependencies (Linux) - name: Set up Python (macOS)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get remove needrestart || echo Ignored
sudo apt-get install -y libssl-dev zlib1g-dev python3-cryptography
- name: Install brew dependencies (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
uses: actions/setup-python@v4
with:
python-version: '3.13'
update-environment: false
architecture: 'arm64'
- name: Set up Python virtual environment (Linux/macOS)
if: runner.os != 'Windows'
run: | run: |
brew install python@3.8 python -m venv --system-site-packages --copies venv
- name: Set up Python virtual environment (Windows)
if: runner.os == 'Windows'
run: |
python.exe -m venv --system-site-packages --copies venv
- name: Install Xcode (macOS) - name: Install Xcode (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
@ -128,46 +134,66 @@ jobs:
- name: Setup the oldest supported version of cmake (macOS) - name: Setup the oldest supported version of cmake (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
uses: jwlawson/actions-setup-cmake@v2.0 uses: jwlawson/actions-setup-cmake@v2.0
with:
cmake-version: '3.17.0' - name: Install python3 cryptography module (Linux)
if: runner.os == 'Linux'
run: |
source venv/bin/activate
python -m pip install --upgrade pip
python -m pip install --upgrade cryptography
python -c "import sys; print(sys.executable)"
python --version
python -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
- name: Install python3 cryptography module (macOS) - name: Install python3 cryptography module (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
run: | run: |
python3.8 -m ensurepip source venv/bin/activate
python3.8 -m pip install --upgrade pip python -m pip install --upgrade pip
python3.8 -m pip install cryptography ARCHFLAGS="-arch arm64" python -m pip install --upgrade cryptography
python -c "import sys; print(sys.executable)"
python --version
python -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
- name: Install python3 cryptography module (Windows) - name: Install python3 cryptography module (Windows)
if: runner.os == 'Windows' if: runner.os == 'Windows'
run: | run: |
C:/hostedtoolcache/windows/Python/3.12.3/x64/python3.exe -m ensurepip .\venv\Scripts\Activate.ps1
C:/hostedtoolcache/windows/Python/3.12.3/x64/python.exe -m pip install --upgrade pip python.exe -m ensurepip
C:/hostedtoolcache/windows/Python/3.12.3/x64/python.exe -m pip install cryptography python.exe -m pip install --upgrade pip
python.exe -m pip install cryptography
python.exe -c "import sys; print(sys.executable)"
python.exe --version
python.exe -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
- name: Configure CMake - name: Configure CMake (Linux/macOS)
run: cmake if: runner.os != 'Windows'
-G "${{matrix.generator}}" run: |
-S ${{github.workspace}} source venv/bin/activate
-B ${{github.workspace}}/build cmake \
-DCMAKE_OSX_ARCHITECTURES=arm64 -G "${{matrix.generator}}" \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -S "${{github.workspace}}" \
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist -B "${{github.workspace}}/build" \
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}} -DCMAKE_OSX_ARCHITECTURES=arm64 \
-DCMAKE_BUILD_TYPE="${{env.BUILD_TYPE}}" \
-DCMAKE_INSTALL_PREFIX="${{github.workspace}}/dist"
- name: Configure CMake (Windows)
if: runner.os == 'Windows'
run: |
.\venv\Scripts\Activate.ps1
cmake `
-G "${{matrix.generator}}" `
-S "${{github.workspace}}" `
-B "${{github.workspace}}/build" `
-DCMAKE_BUILD_TYPE="${{env.BUILD_TYPE}}" `
-DCMAKE_INSTALL_PREFIX="${{github.workspace}}/dist"
- name: Build - name: Build
run: cmake run: cmake
--build ${{github.workspace}}/build --build ${{github.workspace}}/build
--config ${{env.BUILD_TYPE}} --config ${{env.BUILD_TYPE}}
- name: Show python version (macOS)
working-directory: ${{github.workspace}}/build
if: runner.os == 'macOS'
run: |
python3.8 --version
python3.8 -c "import sys; print(sys.executable)"
python3.8 -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
- name: List files (Linux/macOS) - name: List files (Linux/macOS)
if: runner.os != 'Windows' if: runner.os != 'Windows'
run: find .. -ls run: find .. -ls
@ -176,9 +202,19 @@ jobs:
if: runner.os == 'Windows' if: runner.os == 'Windows'
run: Get-ChildItem -Recurse -Name .. run: Get-ChildItem -Recurse -Name ..
- name: Test - name: Test (Linux/macOS)
if: runner.os != 'Windows'
working-directory: ${{github.workspace}}/build working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}} run: |
source ../venv/bin/activate
ctest -C ${{env.BUILD_TYPE}}
- name: Test (Windows)
if: runner.os == 'Windows'
working-directory: ${{github.workspace}}/build
run: |
..\venv\Scripts\Activate.ps1
ctest -C ${{env.BUILD_TYPE}}
- name: Upload the errors - name: Upload the errors
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4

@ -10,13 +10,13 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
# configure basic project information # configure basic project information
project(osslsigncode project(osslsigncode
VERSION 2.9 VERSION 2.10
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files" DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files"
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode" HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
LANGUAGES C) LANGUAGES C)
# force nonstandard version format for development packages # force nonstandard version format for development packages
set(DEV "") set(DEV "-dev")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}${DEV}") set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}${DEV}")
# version and contact information # version and contact information
@ -27,8 +27,15 @@ set(PACKAGE_BUGREPORT "Michal.Trojnara@stunnel.org")
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD_REQUIRED ON)
if(WIN32)
add_definitions(-DUSE_WIN32)
endif()
# load CMake library modules # load CMake library modules
include(FindOpenSSL) include(FindOpenSSL)
if(OPENSSL_VERSION VERSION_LESS "1.1.1")
message(FATAL_ERROR "OpenSSL version must be at least 1.1.1")
endif()
if(OPENSSL_VERSION VERSION_LESS "3.0.0") if(OPENSSL_VERSION VERSION_LESS "3.0.0")
include(FindCURL) include(FindCURL)
endif(OPENSSL_VERSION VERSION_LESS "3.0.0") endif(OPENSSL_VERSION VERSION_LESS "3.0.0")

@ -1,5 +1,13 @@
# osslsigncode change log # osslsigncode change log
### 2.10 (unreleased)
- added compatiblity with the CNG engine version 1.1 or later
- added the "-engineCtrl" option to control hardware and CNG engines
- improved unauthenticated blob support (thanks to Asger Hautop Drewsen)
- added the '-blobFile' option to specify a file containing the blob content
- added PKCS#11 provider support (requires OpenSSL 3.0)
### 2.9 (2024.06.29) ### 2.9 (2024.06.29)
- added a 64 bit long pseudo-random NONCE in the TSA request - added a 64 bit long pseudo-random NONCE in the TSA request

@ -131,17 +131,51 @@ To sign a CAB file containing java class files:
``` ```
Only the 'low' parameter is currently supported. Only the 'low' parameter is currently supported.
If you want to use PKCS11 token, you should indicate PKCS11 engine and module. If you want to use a PKCS#11 token, you should specify the PKCS#11 engine and module.
An example of using osslsigncode with SoftHSM: An example of using osslsigncode with SoftHSM:
``` ```
osslsigncode sign \ osslsigncode sign \
-pkcs11engine /usr/lib64/engines-1.1/pkcs11.so \ -engine /usr/lib64/engines-1.1/pkcs11.so \
-pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \ -pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \
-pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \ -pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \
-key 'pkcs11:token=softhsm-token;object=key' \ -key 'pkcs11:token=softhsm-token;object=key' \
-in yourapp.exe -out yourapp-signed.exe -in yourapp.exe -out yourapp-signed.exe
``` ```
Since OpenSSL 3.0, you can use a PKCS#11 token with the PKCS#11 provider.
An example of using osslsigncode with OpenSC:
```
osslsigncode sign \
-provider /usr/lib64/ossl-modules/pkcs11prov.so \
-pkcs11module /usr/lib64/opensc-pkcs11.so \
-pkcs11cert 'pkcs11:token=my-token;object=cert' \
-key 'pkcs11:token=my-token;object=key' \
-in yourapp.exe -out yourapp-signed.exe
```
You can use a certificate and key stored in the Windows Certificate Store with
the CNG engine version 1.1 or later. For more information, refer to
https://www.stunnel.org/cng-engine.html
A non-commercial edition of CNG engine is available for testing, personal,
educational, or research purposes.
To use the CNG engine with osslsigncode, ensure that the `cng.dll` library is
placed in the same directory as the `osslsigncode.exe` executable.
Below is an example of how to use osslsigncode with the CNG engine:
```
osslsigncode sign \
-engine cng \
-pkcs11cert osslsigncode_cert \
-key osslsigncode_cert \
-engineCtrl store_flags:0 \
-engineCtrl store_name:MY \
-engineCtrl PIN:yourpass \
-in yourapp.exe -out yourapp-signed.exe
```
You can check that the signed file is correct by right-clicking You can check that the signed file is correct by right-clicking
on it in Windows and choose Properties --> Digital Signatures, on it in Windows and choose Properties --> Digital Signatures,
and then choose the signature from the list, and click on and then choose the signature from the list, and click on

33
appx.c

@ -29,11 +29,6 @@
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#endif /* PRIX64 */ #endif /* PRIX64 */
#if defined(_MSC_VER)
#define fseeko _fseeki64
#define ftello _ftelli64
#endif /* _MSC_VER */
#define EOCDR_SIZE 22 #define EOCDR_SIZE 22
#define ZIP64_EOCD_LOCATOR_SIZE 20 #define ZIP64_EOCD_LOCATOR_SIZE 20
#define ZIP64_HEADER 0x01 #define ZIP64_HEADER 0x01
@ -1493,6 +1488,7 @@ static int zipAppendSignatureFile(BIO *bio, ZIP_FILE *zip, uint8_t *data, uint64
if (!get_current_position(bio, &offset)) { if (!get_current_position(bio, &offset)) {
fprintf(stderr, "Unable to get offset\n"); fprintf(stderr, "Unable to get offset\n");
OPENSSL_free(header.fileName);
OPENSSL_free(dataToWrite); OPENSSL_free(dataToWrite);
return 0; /* FAILED */ return 0; /* FAILED */
} }
@ -1502,6 +1498,7 @@ static int zipAppendSignatureFile(BIO *bio, ZIP_FILE *zip, uint8_t *data, uint64
size_t check; size_t check;
if (!BIO_write_ex(bio, dataToWrite + written, toWrite, &check) if (!BIO_write_ex(bio, dataToWrite + written, toWrite, &check)
|| check != toWrite) { || check != toWrite) {
OPENSSL_free(header.fileName);
OPENSSL_free(dataToWrite); OPENSSL_free(dataToWrite);
return 0; /* FAILED */ return 0; /* FAILED */
} }
@ -1596,6 +1593,7 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
{ {
size_t check; size_t check;
ZIP_LOCAL_HEADER header; ZIP_LOCAL_HEADER header;
int ret = 0;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) { if (entry->offsetOfLocalHeader >= (uint64_t)zip->fileSize) {
@ -1606,7 +1604,7 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
return 0; /* FAILED */ return 0; /* FAILED */
} }
if (!zipReadLocalHeader(&header, zip, entry->compressedSize)) { if (!zipReadLocalHeader(&header, zip, entry->compressedSize)) {
return 0; /* FAILED */ goto out;
} }
if (entry->overrideData) { if (entry->overrideData) {
header.compressedSize = entry->overrideData->compressedSize; header.compressedSize = entry->overrideData->compressedSize;
@ -1617,14 +1615,14 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
if (entry->overrideData) { if (entry->overrideData) {
if (!BIO_write_ex(bio, entry->overrideData->data, entry->overrideData->compressedSize, &check) if (!BIO_write_ex(bio, entry->overrideData->data, entry->overrideData->compressedSize, &check)
|| check != entry->overrideData->compressedSize) { || check != entry->overrideData->compressedSize) {
return 0; /* FAILED */ goto out;
} }
if (entry->compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) { if (entry->compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
fprintf(stderr, "Corrupted compressedSize : 0x%08" PRIX64 "\n", entry->compressedSize); fprintf(stderr, "Corrupted compressedSize : 0x%08" PRIX64 "\n", entry->compressedSize);
return 0; /* FAILED */ goto out;
} }
if (fseeko(zip->file, (int64_t)entry->compressedSize, SEEK_CUR) < 0) { if (fseeko(zip->file, (int64_t)entry->compressedSize, SEEK_CUR) < 0) {
return 0; /* FAILED */ goto out;
} }
*sizeOnDisk += entry->overrideData->compressedSize; *sizeOnDisk += entry->overrideData->compressedSize;
} else { } else {
@ -1635,12 +1633,12 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
size_t size = fread(data, 1, toWrite, zip->file); size_t size = fread(data, 1, toWrite, zip->file);
if (size != toWrite) { if (size != toWrite) {
OPENSSL_free(data); OPENSSL_free(data);
return 0; /* FAILED */ goto out;
} }
if (!BIO_write_ex(bio, data, toWrite, &check) if (!BIO_write_ex(bio, data, toWrite, &check)
|| check != toWrite) { || check != toWrite) {
OPENSSL_free(data); OPENSSL_free(data);
return 0; /* FAILED */ goto out;
} }
*sizeOnDisk += toWrite; *sizeOnDisk += toWrite;
len -= toWrite; len -= toWrite;
@ -1659,19 +1657,21 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
} }
if (zip->isZip64) { if (zip->isZip64) {
if (fseeko(zip->file, 24, SEEK_CUR) < 0) { if (fseeko(zip->file, 24, SEEK_CUR) < 0) {
return 0; /* FAILED */ goto out;
} }
*sizeOnDisk += 24; *sizeOnDisk += 24;
} else { } else {
if (fseeko(zip->file, 16, SEEK_CUR) < 0) { if (fseeko(zip->file, 16, SEEK_CUR) < 0) {
return 0; /* FAILED */ goto out;
} }
*sizeOnDisk += 16; *sizeOnDisk += 16;
} }
} }
ret = 1; /* OK */
out:
OPENSSL_free(header.fileName); OPENSSL_free(header.fileName);
OPENSSL_free(header.extraField); OPENSSL_free(header.extraField);
return 1; /* OK */ return ret;
} }
/* /*
@ -1840,6 +1840,8 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
uncompressedSize = entry->uncompressedSize; uncompressedSize = entry->uncompressedSize;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
if (!zipReadLocalHeader(&header, zip, compressedSize)) { if (!zipReadLocalHeader(&header, zip, compressedSize)) {
OPENSSL_free(header.fileName);
OPENSSL_free(header.extraField);
return 0; /* FAILED */ return 0; /* FAILED */
} }
if (header.fileNameLen != entry->fileNameLen if (header.fileNameLen != entry->fileNameLen
@ -1848,6 +1850,8 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
|| header.uncompressedSize != uncompressedSize || header.uncompressedSize != uncompressedSize
|| header.compression != entry->compression) { || header.compression != entry->compression) {
fprintf(stderr, "Local header does not match central directory entry\n"); fprintf(stderr, "Local header does not match central directory entry\n");
OPENSSL_free(header.fileName);
OPENSSL_free(header.extraField);
return 0; /* FAILED */ return 0; /* FAILED */
} }
/* we don't really need those */ /* we don't really need those */
@ -2149,6 +2153,7 @@ static int zipDeflate(uint8_t *dest, uint64_t *destLen, uint8_t *source, uLong s
err = deflateInit2(&stream, 8, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); err = deflateInit2(&stream, 8, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
if (err != Z_OK) { if (err != Z_OK) {
deflateEnd(&stream);
return err; return err;
} }
stream.next_out = dest; stream.next_out = dest;

39
cat.c

@ -55,8 +55,8 @@ FILE_FORMAT file_format_cat = {
/* Prototypes */ /* Prototypes */
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize); static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize);
static int cat_add_ms_ctl_object(PKCS7 *p7); static int cat_add_content_type(PKCS7 *p7, PKCS7 *cursig);
static int cat_sign_ms_ctl_content(PKCS7 *p7, PKCS7 *contents); static int cat_sign_content(PKCS7 *p7, PKCS7 *contents);
static int cat_list_content(PKCS7 *p7); static int cat_list_content(PKCS7 *p7);
static int cat_print_content_member_digest(ASN1_TYPE *content); static int cat_print_content_member_digest(ASN1_TYPE *content);
static int cat_print_content_member_name(ASN1_TYPE *content); static int cat_print_content_member_name(ASN1_TYPE *content);
@ -161,17 +161,17 @@ static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
fprintf(stderr, "Creating a new signature failed\n"); fprintf(stderr, "Creating a new signature failed\n");
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
if (!cat_add_ms_ctl_object(p7)) {
fprintf(stderr, "Adding MS_CTL_OBJID failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!ctx->cat_ctx->p7 || !ctx->cat_ctx->p7->d.sign || !ctx->cat_ctx->p7->d.sign->contents) { if (!ctx->cat_ctx->p7 || !ctx->cat_ctx->p7->d.sign || !ctx->cat_ctx->p7->d.sign->contents) {
fprintf(stderr, "Failed to get content\n"); fprintf(stderr, "Failed to get content\n");
PKCS7_free(p7); PKCS7_free(p7);
return NULL; /* FAILED */ return NULL; /* FAILED */
} }
if (!cat_sign_ms_ctl_content(p7, ctx->cat_ctx->p7->d.sign->contents)) { if (!cat_add_content_type(p7, ctx->cat_ctx->p7)) {
fprintf(stderr, "Adding content type failed\n");
PKCS7_free(p7);
return NULL; /* FAILED */
}
if (!cat_sign_content(p7, ctx->cat_ctx->p7->d.sign->contents)) {
fprintf(stderr, "Failed to set signed content\n"); fprintf(stderr, "Failed to set signed content\n");
PKCS7_free(p7); PKCS7_free(p7);
return NULL; /* FAILED */ return NULL; /* FAILED */
@ -251,15 +251,30 @@ static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize)
} }
/* /*
* Add "1.3.6.1.4.1.311.10.1" MS_CTL_OBJID signed attribute * Add a content type OID to the PKCS#7 signature structure.
* The content type can be:
* - "1.3.6.1.4.1.311.10.1" (MS_CTL_OBJID) for Certificate Trust Lists (CTL),
* - "1.3.6.1.4.1.311.2.1.4" (SPC_INDIRECT_DATA_OBJID) for Authenticode data.
* [in, out] p7: new PKCS#7 signature * [in, out] p7: new PKCS#7 signature
* [in] cursig: current PKCS#7 signature to determine content type
* [returns] 0 on error or 1 on success * [returns] 0 on error or 1 on success
*/ */
static int cat_add_ms_ctl_object(PKCS7 *p7) static int cat_add_content_type(PKCS7 *p7, PKCS7 *cursig)
{ {
const char *content_type;
STACK_OF(PKCS7_SIGNER_INFO) *signer_info; STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
PKCS7_SIGNER_INFO *si; PKCS7_SIGNER_INFO *si;
if (is_content_type(cursig, SPC_INDIRECT_DATA_OBJID)) {
/* Authenticode content */
content_type = SPC_INDIRECT_DATA_OBJID;
} else if (is_content_type(cursig, MS_CTL_OBJID)) {
/* Certificate Trust List (CTL) */
content_type = MS_CTL_OBJID;
} else {
fprintf(stderr, "Unsupported content type\n");
return 0; /* FAILED */
}
signer_info = PKCS7_get_signer_info(p7); signer_info = PKCS7_get_signer_info(p7);
if (!signer_info) if (!signer_info)
return 0; /* FAILED */ return 0; /* FAILED */
@ -267,7 +282,7 @@ static int cat_add_ms_ctl_object(PKCS7 *p7)
if (!si) if (!si)
return 0; /* FAILED */ return 0; /* FAILED */
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
V_ASN1_OBJECT, OBJ_txt2obj(MS_CTL_OBJID, 1))) V_ASN1_OBJECT, OBJ_txt2obj(content_type, 1)))
return 0; /* FAILED */ return 0; /* FAILED */
return 1; /* OK */ return 1; /* OK */
} }
@ -280,7 +295,7 @@ static int cat_add_ms_ctl_object(PKCS7 *p7)
* [in] contents: Certificate Trust List (CTL) * [in] contents: Certificate Trust List (CTL)
* [returns] 0 on error or 1 on success * [returns] 0 on error or 1 on success
*/ */
static int cat_sign_ms_ctl_content(PKCS7 *p7, PKCS7 *contents) static int cat_sign_content(PKCS7 *p7, PKCS7 *contents)
{ {
u_char *content; u_char *content;
int seqhdrlen, content_length; int seqhdrlen, content_length;

@ -219,6 +219,7 @@ if(Python3_FOUND AND NOT cryptography_error)
add_test(NAME "added_${ext}" add_test(NAME "added_${ext}"
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "add" COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "add"
"-addUnauthenticatedBlob" "-addUnauthenticatedBlob"
"-blobFile" "${FILES}/unsigned.exe"
"-add-msi-dse" "-h" "sha512" "-add-msi-dse" "-h" "sha512"
"-in" "${FILES}/signed.${ext}" "-in" "${FILES}/signed.${ext}"
"-out" "${FILES}/added.${ext}") "-out" "${FILES}/added.${ext}")

@ -165,73 +165,76 @@ int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx) PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
{ {
int i, signer = -1; int i, signer = -1;
PKCS7 *p7;
PKCS7_SIGNER_INFO *si = NULL; PKCS7_SIGNER_INFO *si = NULL;
STACK_OF(X509) *chain = NULL; STACK_OF(X509) *chain = NULL;
PKCS7 *p7 = PKCS7_new();
if (!p7)
return NULL;
p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_set_type(p7, NID_pkcs7_signed);
PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_content_new(p7, NID_pkcs7_data);
if (ctx->options->cert != NULL) {
/* /* find the signer's certificate located somewhere in the whole certificate chain */
* the private key and corresponding certificate are parsed from the PKCS12 for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
* structure or loaded from the security token, so we may omit to check X509 *signcert = sk_X509_value(ctx->options->certs, i);
* the consistency of a private key with the public key in an X509 certificate
*/ if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, ctx->options->cert, ctx->options->pkey, si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
ctx->options->md); signer = i;
if (si == NULL) if (signer > 0)
return NULL; /* FAILED */ printf("Warning: For optimal performance, consider placing the signer certificate at the beginning of the certificate chain.\n");
} else { break;
/* find the signer's certificate located somewhere in the whole certificate chain */
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
X509 *signcert = sk_X509_value(ctx->options->certs, i);
if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
signer = i;
break;
}
}
if (si == NULL) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
ctx->options->certfile);
return NULL; /* FAILED */
} }
} }
if (!si) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
ctx->options->certfile ? ctx->options->certfile : ctx->options->p11cert);
#else
ctx->options->certfile);
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
goto err;
}
if (!pkcs7_signer_info_add_signing_time(si, ctx)) { if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
if (!pkcs7_signer_info_add_purpose(si, ctx)) { if (!pkcs7_signer_info_add_purpose(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
if ((ctx->options->desc || ctx->options->url) && if ((ctx->options->desc || ctx->options->url) &&
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) { !pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
fprintf(stderr, "Couldn't allocate memory for opus info\n"); fprintf(stderr, "Couldn't allocate memory for opus info\n");
return NULL; /* FAILED */ goto err;
} }
if ((ctx->options->nested_number >= 0) && if ((ctx->options->nested_number >= 0) &&
!pkcs7_signer_info_add_sequence_number(si, ctx)) { !pkcs7_signer_info_add_sequence_number(si, ctx)) {
return NULL; /* FAILED */ goto err;
} }
/* create X509 chain sorted in ascending order by their DER encoding */ /* create X509 chain sorted in ascending order by their DER encoding */
chain = X509_chain_get_sorted(ctx, signer); chain = X509_chain_get_sorted(ctx, signer);
if (chain == NULL) { if (!chain) {
fprintf(stderr, "Failed to create a sorted certificate chain\n"); fprintf(stderr, "Failed to create a sorted certificate chain\n");
return NULL; /* FAILED */ goto err;
} }
/* add sorted certificate chain */ /* add sorted certificate chain */
for (i=0; i<sk_X509_num(chain); i++) { for (i=0; i<sk_X509_num(chain); i++) {
PKCS7_add_certificate(p7, sk_X509_value(chain, i)); (void)PKCS7_add_certificate(p7, sk_X509_value(chain, i));
} }
/* add crls */ /* add crls */
if (ctx->options->crls) { if (ctx->options->crls) {
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++) for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i)); (void)PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
} }
sk_X509_free(chain); sk_X509_free(chain);
return p7; /* OK */ return p7; /* OK */
err:
PKCS7_free(p7);
return NULL; /* FAILED */
} }
/* /*
@ -461,7 +464,7 @@ void print_hash(const char *descript1, const char *descript2, const u_char *mdbu
} }
/* /*
* [in] p7: new PKCS#7 signature * [in] p7: PKCS#7 signature
* [in] objid: Microsoft OID Authenticode * [in] objid: Microsoft OID Authenticode
* [returns] 0 on error or 1 on success * [returns] 0 on error or 1 on success
*/ */
@ -732,11 +735,6 @@ static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
int i; int i;
STACK_OF(X509) *chain = sk_X509_new(X509_compare); STACK_OF(X509) *chain = sk_X509_new(X509_compare);
/* add the signer's certificate */
if (ctx->options->cert != NULL && !sk_X509_push(chain, ctx->options->cert)) {
sk_X509_free(chain);
return NULL;
}
if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) { if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) {
sk_X509_free(chain); sk_X509_free(chain);
return NULL; return NULL;

5
msi.c

@ -1785,7 +1785,6 @@ static int ministream_save(MSI_DIRENT *dirent, BIO *outdata, MSI_OUT *out)
dirent->entry->startSectorLocation = out->sectorNum; dirent->entry->startSectorLocation = out->sectorNum;
/* ministream save */ /* ministream save */
BIO_write(outdata, out->ministream, (int)out->miniStreamLen); BIO_write(outdata, out->ministream, (int)out->miniStreamLen);
OPENSSL_free(out->ministream);
/* fill to the end with known data, such as all zeroes */ /* fill to the end with known data, such as all zeroes */
if (out->miniStreamLen % out->sectorSize > 0) { if (out->miniStreamLen % out->sectorSize > 0) {
remain = out->sectorSize - out->miniStreamLen % out->sectorSize; remain = out->sectorSize - out->miniStreamLen % out->sectorSize;
@ -2186,6 +2185,8 @@ static int msiout_set(MSI_FILE *msi, uint32_t len_msi, uint32_t len_msiex, MSI_O
out->header = header_new(msi->m_hdr, out); out->header = header_new(msi->m_hdr, out);
out->minifatMemallocCount = msi->m_hdr->numMiniFATSector; out->minifatMemallocCount = msi->m_hdr->numMiniFATSector;
out->fatMemallocCount = msi->m_hdr->numFATSector; out->fatMemallocCount = msi->m_hdr->numFATSector;
out->difatMemallocCount = 0;
out->difat = NULL;
out->ministream = NULL; out->ministream = NULL;
out->minifat = OPENSSL_malloc((uint64_t)out->minifatMemallocCount * out->sectorSize); out->minifat = OPENSSL_malloc((uint64_t)out->minifatMemallocCount * out->sectorSize);
out->fat = OPENSSL_malloc((uint64_t)out->fatMemallocCount * out->sectorSize); out->fat = OPENSSL_malloc((uint64_t)out->fatMemallocCount * out->sectorSize);
@ -2226,7 +2227,9 @@ static int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, uint
out: out:
OPENSSL_free(out.header); OPENSSL_free(out.header);
OPENSSL_free(out.fat); OPENSSL_free(out.fat);
OPENSSL_free(out.difat);
OPENSSL_free(out.minifat); OPENSSL_free(out.minifat);
OPENSSL_free(out.ministream);
return ret; return ret;
} }

File diff suppressed because it is too large Load Diff

@ -66,7 +66,9 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/safestack.h> #include <openssl/safestack.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/store.h>
#include <openssl/ts.h> #include <openssl/ts.h>
#include <openssl/ui.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> /* X509_PURPOSE */ #include <openssl/x509v3.h> /* X509_PURPOSE */
@ -90,7 +92,9 @@
#ifdef _MSC_VER #ifdef _MSC_VER
/* not WIN32, because strcasecmp exists in MinGW */ /* not WIN32, because strcasecmp exists in MinGW */
#define strcasecmp _stricmp #define strcasecmp _stricmp
#endif #define fseeko _fseeki64
#define ftello _ftelli64
#endif /* _MSC_VER */
#ifdef WIN32 #ifdef WIN32
#define remove_file(filename) _unlink(filename) #define remove_file(filename) _unlink(filename)
@ -242,6 +246,16 @@ typedef enum {
typedef unsigned char u_char; typedef unsigned char u_char;
#ifndef OPENSSL_NO_ENGINE
typedef struct {
ASN1_OCTET_STRING *cmd;
ASN1_OCTET_STRING *param;
} EngineControl;
DECLARE_ASN1_FUNCTIONS(EngineControl)
DEFINE_STACK_OF(EngineControl)
#endif /* OPENSSL_NO_ENGINE */
typedef struct { typedef struct {
char *infile; char *infile;
char *outfile; char *outfile;
@ -257,6 +271,7 @@ typedef struct {
char *p11module; char *p11module;
char *p11cert; char *p11cert;
int login; int login;
STACK_OF(EngineControl) *engine_ctrls;
#endif /* OPENSSL_NO_ENGINE */ #endif /* OPENSSL_NO_ENGINE */
int askpass; int askpass;
char *readpass; char *readpass;
@ -274,6 +289,7 @@ typedef struct {
char *proxy; char *proxy;
int noverifypeer; int noverifypeer;
int addBlob; int addBlob;
const char *blob_file;
int nest; int nest;
int index; int index;
int ignore_timestamp; int ignore_timestamp;
@ -292,9 +308,9 @@ typedef struct {
int jp; int jp;
#if OPENSSL_VERSION_NUMBER>=0x30000000L #if OPENSSL_VERSION_NUMBER>=0x30000000L
int legacy; int legacy;
char *provider;
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */ #endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
EVP_PKEY *pkey; EVP_PKEY *pkey;
X509 *cert;
STACK_OF(X509) *certs; STACK_OF(X509) *certs;
STACK_OF(X509) *xcerts; STACK_OF(X509) *xcerts;
STACK_OF(X509_CRL) *crls; STACK_OF(X509_CRL) *crls;

@ -4,11 +4,60 @@
import os import os
import datetime import datetime
import cryptography import cryptography
from cryptography import x509
from cryptography.x509.oid import NameOID # Explicit imports of cryptography submodules
from cryptography.hazmat.primitives import hashes import cryptography.x509
from cryptography.hazmat.primitives import serialization import cryptography.x509.oid
from cryptography.hazmat.primitives.asymmetric import rsa import cryptography.hazmat.primitives.hashes
import cryptography.hazmat.primitives.asymmetric.rsa
import cryptography.hazmat.primitives.serialization
import cryptography.hazmat.primitives.serialization.pkcs12
# Import classes and functions from the cryptography module
from cryptography.x509 import (
AuthorityKeyIdentifier,
BasicConstraints,
Certificate,
CertificateBuilder,
CertificateRevocationListBuilder,
CRLDistributionPoints,
CRLNumber,
CRLReason,
DistributionPoint,
DNSName,
ExtendedKeyUsage,
KeyUsage,
Name,
NameAttribute,
NameConstraints,
random_serial_number,
RevokedCertificateBuilder,
ReasonFlags,
SubjectKeyIdentifier,
UniformResourceIdentifier
)
from cryptography.x509.oid import (
ExtendedKeyUsageOID,
NameOID
)
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives.asymmetric.rsa import (
generate_private_key,
RSAPrivateKey
)
from cryptography.hazmat.primitives.serialization import (
BestAvailableEncryption,
Encoding,
NoEncryption,
PrivateFormat
)
from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates
try:
if cryptography.__version__ >= '38.0.0':
from cryptography.hazmat.primitives.serialization.pkcs12 import PBES
except ImportError:
pass
RESULT_PATH = os.getcwd() RESULT_PATH = os.getcwd()
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/") CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
@ -28,25 +77,25 @@ class X509Extensions():
self.port = cdp_port self.port = cdp_port
self.name = cdp_name self.name = cdp_name
def create_x509_name(self, common_name) -> x509.Name: def create_x509_name(self, common_name) -> Name:
"""Return x509.Name""" """Return x509.Name"""
return x509.Name( return Name(
[ [
x509.NameAttribute(NameOID.COUNTRY_NAME, "PL"), NameAttribute(NameOID.COUNTRY_NAME, "PL"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Mazovia Province"), NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Mazovia Province"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Warsaw"), NameAttribute(NameOID.LOCALITY_NAME, "Warsaw"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "osslsigncode"), NameAttribute(NameOID.ORGANIZATION_NAME, "osslsigncode"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, self.unit_name), NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, self.unit_name),
x509.NameAttribute(NameOID.COMMON_NAME, common_name) NameAttribute(NameOID.COMMON_NAME, common_name)
] ]
) )
def create_x509_crldp(self) -> x509.CRLDistributionPoints: def create_x509_crldp(self) -> CRLDistributionPoints:
"""Return x509.CRLDistributionPoints""" """Return x509.CRLDistributionPoints"""
return x509.CRLDistributionPoints( return CRLDistributionPoints(
[ [
x509.DistributionPoint( DistributionPoint(
full_name=[x509.UniformResourceIdentifier( full_name=[UniformResourceIdentifier(
"http://127.0.0.1:" + str(self.port) + "/" + str(self.name)) "http://127.0.0.1:" + str(self.port) + "/" + str(self.name))
], ],
relative_name=None, relative_name=None,
@ -56,10 +105,10 @@ class X509Extensions():
] ]
) )
def create_x509_name_constraints(self) -> x509.NameConstraints: def create_x509_name_constraints(self) -> NameConstraints:
"""Return x509.NameConstraints""" """Return x509.NameConstraints"""
return x509.NameConstraints( return NameConstraints(
permitted_subtrees = [x509.DNSName('test.com'), x509.DNSName('test.org')], permitted_subtrees = [DNSName('test.com'), DNSName('test.org')],
excluded_subtrees = None excluded_subtrees = None
) )
@ -71,14 +120,14 @@ class IntermediateCACertificate(X509Extensions):
self.issuer_key = issuer_key self.issuer_key = issuer_key
super().__init__("Certification Authority", 0, None) super().__init__("Certification Authority", 0, None)
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey): def make_cert(self) -> (Certificate, RSAPrivateKey):
"""Generate intermediate CA certificate""" """Generate intermediate CA certificate"""
key = rsa.generate_private_key(public_exponent=65537, key_size=2048) key = generate_private_key(public_exponent=65537, key_size=2048)
key_public = key.public_key() key_public = key.public_key()
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
) )
key_usage = x509.KeyUsage( key_usage = KeyUsage(
digital_signature=True, digital_signature=True,
content_commitment=False, content_commitment=False,
key_encipherment=False, key_encipherment=False,
@ -90,22 +139,22 @@ class IntermediateCACertificate(X509Extensions):
decipher_only=False decipher_only=False
) )
cert = ( cert = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(self.create_x509_name("Intermediate CA")) .subject_name(self.create_x509_name("Intermediate CA"))
.issuer_name(self.issuer_cert.subject) .issuer_name(self.issuer_cert.subject)
.public_key(key_public) .public_key(key_public)
.serial_number(x509.random_serial_number()) .serial_number(random_serial_number())
.not_valid_before(date_20180101) .not_valid_before(date_20180101)
.not_valid_after(date_20180101 + datetime.timedelta(days=7300)) .not_valid_after(date_20180101 + datetime.timedelta(days=7300))
.add_extension(x509.BasicConstraints(ca=True, path_length=0), critical=True) .add_extension(BasicConstraints(ca=True, path_length=0), critical=True)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(key_public), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(key_public), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(key_usage, critical=True) .add_extension(key_usage, critical=True)
.sign(self.issuer_key, hashes.SHA256()) .sign(self.issuer_key, SHA256())
) )
file_path=os.path.join(CERTS_PATH, "intermediateCA.pem") file_path=os.path.join(CERTS_PATH, "intermediateCA.pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(cert.public_bytes(encoding=Encoding.PEM))
return cert, key return cert, key
@ -114,7 +163,7 @@ class RootCACertificate(X509Extensions):
"""Base class for Root CA certificate""" """Base class for Root CA certificate"""
def __init__(self): def __init__(self):
self.key_usage = x509.KeyUsage( self.key_usage = KeyUsage(
digital_signature=True, digital_signature=True,
content_commitment=False, content_commitment=False,
key_encipherment=False, key_encipherment=False,
@ -127,7 +176,7 @@ class RootCACertificate(X509Extensions):
) )
super().__init__("Certification Authority", 0, None) super().__init__("Certification Authority", 0, None)
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey): def make_cert(self) -> (Certificate, RSAPrivateKey):
"""Generate CA certificates""" """Generate CA certificates"""
ca_root, root_key = self.make_ca_cert("Trusted Root CA", "CAroot.pem") ca_root, root_key = self.make_ca_cert("Trusted Root CA", "CAroot.pem")
ca_cert, ca_key = self.make_ca_cert("Root CA", "CACert.pem") ca_cert, ca_key = self.make_ca_cert("Root CA", "CACert.pem")
@ -136,52 +185,52 @@ class RootCACertificate(X509Extensions):
def make_ca_cert(self, common_name, file_name) -> None: def make_ca_cert(self, common_name, file_name) -> None:
"""Generate self-signed root CA certificate""" """Generate self-signed root CA certificate"""
ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) ca_key = generate_private_key(public_exponent=65537, key_size=2048)
ca_public = ca_key.public_key() ca_public = ca_key.public_key()
authority_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(ca_public) authority_key = AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
name = self.create_x509_name(common_name) name = self.create_x509_name(common_name)
ca_cert = ( ca_cert = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(name) .subject_name(name)
.issuer_name(name) .issuer_name(name)
.public_key(ca_public) .public_key(ca_public)
.serial_number(x509.random_serial_number()) .serial_number(random_serial_number())
.not_valid_before(date_20170101) .not_valid_before(date_20170101)
.not_valid_after(date_20170101 + datetime.timedelta(days=7300)) .not_valid_after(date_20170101 + datetime.timedelta(days=7300))
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) .add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(self.key_usage, critical=True) .add_extension(self.key_usage, critical=True)
.sign(ca_key, hashes.SHA256()) .sign(ca_key, SHA256())
) )
file_path=os.path.join(CERTS_PATH, file_name) file_path=os.path.join(CERTS_PATH, file_name)
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(ca_cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(ca_cert.public_bytes(encoding=Encoding.PEM))
return ca_cert, ca_key return ca_cert, ca_key
def make_cross_cert(self, ca_root, root_key, ca_cert, ca_key) -> None: def make_cross_cert(self, ca_root, root_key, ca_cert, ca_key) -> None:
"""Generate cross-signed root CA certificate""" """Generate cross-signed root CA certificate"""
ca_public = ca_key.public_key() ca_public = ca_key.public_key()
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
ca_root.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value ca_root.extensions.get_extension_for_class(SubjectKeyIdentifier).value
) )
ca_cross = ( ca_cross = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(ca_cert.subject) .subject_name(ca_cert.subject)
.issuer_name(ca_root.subject) .issuer_name(ca_root.subject)
.public_key(ca_public) .public_key(ca_public)
.serial_number(ca_cert.serial_number) .serial_number(ca_cert.serial_number)
.not_valid_before(date_20180101) .not_valid_before(date_20180101)
.not_valid_after(date_20180101 + datetime.timedelta(days=7300)) .not_valid_after(date_20180101 + datetime.timedelta(days=7300))
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) .add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(self.key_usage, critical=True) .add_extension(self.key_usage, critical=True)
.sign(root_key, hashes.SHA256()) .sign(root_key, SHA256())
) )
file_path=os.path.join(CERTS_PATH, "CAcross.pem") file_path=os.path.join(CERTS_PATH, "CAcross.pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(ca_cross.public_bytes(encoding=serialization.Encoding.PEM)) file.write(ca_cross.public_bytes(encoding=Encoding.PEM))
def write_key(self, key, file_name) -> None: def write_key(self, key, file_name) -> None:
"""Write a private RSA key""" """Write a private RSA key"""
@ -194,27 +243,27 @@ class RootCACertificate(X509Extensions):
file_path = os.path.join(CERTS_PATH, file_name + "p.pem") file_path = os.path.join(CERTS_PATH, file_name + "p.pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(key.private_bytes( file.write(key.private_bytes(
encoding=serialization.Encoding.PEM, encoding=Encoding.PEM,
format=serialization.PrivateFormat.PKCS8, format=PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(PASSWORD.encode()) encryption_algorithm=BestAvailableEncryption(PASSWORD.encode())
) )
) )
# Write decrypted key in PEM format # Write decrypted key in PEM format
file_path = os.path.join(CERTS_PATH, file_name + ".pem") file_path = os.path.join(CERTS_PATH, file_name + ".pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(key.private_bytes( file.write(key.private_bytes(
encoding=serialization.Encoding.PEM, encoding=Encoding.PEM,
format=serialization.PrivateFormat.PKCS8, format=PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption() encryption_algorithm=NoEncryption()
) )
) )
# Write the key in DER format # Write the key in DER format
file_path = os.path.join(CERTS_PATH, file_name + ".der") file_path = os.path.join(CERTS_PATH, file_name + ".der")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(key.private_bytes( file.write(key.private_bytes(
encoding=serialization.Encoding.DER, encoding=Encoding.DER,
format=serialization.PrivateFormat.PKCS8, format=PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption() encryption_algorithm=NoEncryption()
) )
) )
@ -225,13 +274,13 @@ class TSARootCACertificate(X509Extensions):
def __init__(self): def __init__(self):
super().__init__("Timestamp Authority Root CA", 0, None) super().__init__("Timestamp Authority Root CA", 0, None)
def make_cert(self) -> (x509.Certificate, rsa.RSAPrivateKey): def make_cert(self) -> (Certificate, RSAPrivateKey):
"""Generate a Time Stamp Authority certificate""" """Generate a Time Stamp Authority certificate"""
ca_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) ca_key = generate_private_key(public_exponent=65537, key_size=2048)
ca_public = ca_key.public_key() ca_public = ca_key.public_key()
authority_key = x509.AuthorityKeyIdentifier.from_issuer_public_key(ca_public) authority_key = AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
name = self.create_x509_name("TSA Root CA") name = self.create_x509_name("TSA Root CA")
key_usage = x509.KeyUsage( key_usage = KeyUsage(
digital_signature=False, digital_signature=False,
content_commitment=False, content_commitment=False,
key_encipherment=False, key_encipherment=False,
@ -243,22 +292,22 @@ class TSARootCACertificate(X509Extensions):
decipher_only=False decipher_only=False
) )
ca_cert = ( ca_cert = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(name) .subject_name(name)
.issuer_name(name) .issuer_name(name)
.public_key(ca_public) .public_key(ca_public)
.serial_number(x509.random_serial_number()) .serial_number(random_serial_number())
.not_valid_before(date_20170101) .not_valid_before(date_20170101)
.not_valid_after(date_20170101 + datetime.timedelta(days=7300)) .not_valid_after(date_20170101 + datetime.timedelta(days=7300))
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True) .add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(ca_public), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(key_usage, critical=True) .add_extension(key_usage, critical=True)
.sign(ca_key, hashes.SHA256()) .sign(ca_key, SHA256())
) )
file_path=os.path.join(CERTS_PATH, "TSACA.pem") file_path=os.path.join(CERTS_PATH, "TSACA.pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(ca_cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(ca_cert.public_bytes(encoding=Encoding.PEM))
return ca_cert, ca_key return ca_cert, ca_key
@ -267,14 +316,14 @@ class TSARootCACertificate(X509Extensions):
file_path = os.path.join(CERTS_PATH, file_name + ".key") file_path = os.path.join(CERTS_PATH, file_name + ".key")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(key.private_bytes( file.write(key.private_bytes(
encoding=serialization.Encoding.PEM, encoding=Encoding.PEM,
format=serialization.PrivateFormat.PKCS8, format=PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption() encryption_algorithm=NoEncryption()
) )
) )
class Certificate(X509Extensions): class LeafCertificate(X509Extensions):
"""Base class for a leaf certificate""" """Base class for a leaf certificate"""
def __init__(self, issuer_cert, issuer_key, unit_name, common_name, cdp_port, cdp_name): def __init__(self, issuer_cert, issuer_key, unit_name, common_name, cdp_port, cdp_name):
@ -284,78 +333,78 @@ class Certificate(X509Extensions):
self.common_name = common_name self.common_name = common_name
super().__init__(unit_name, cdp_port, cdp_name) super().__init__(unit_name, cdp_port, cdp_name)
def make_cert(self, public_key, not_before, days) -> x509.Certificate: def make_cert(self, public_key, not_before, days) -> Certificate:
"""Generate a leaf certificate""" """Generate a leaf certificate"""
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
) )
extended_key_usage = x509.ExtendedKeyUsage( extended_key_usage = ExtendedKeyUsage(
[x509.oid.ExtendedKeyUsageOID.CODE_SIGNING] [ExtendedKeyUsageOID.CODE_SIGNING]
) )
cert = ( cert = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(self.create_x509_name(self.common_name)) .subject_name(self.create_x509_name(self.common_name))
.issuer_name(self.issuer_cert.subject) .issuer_name(self.issuer_cert.subject)
.public_key(public_key) .public_key(public_key)
.serial_number(x509.random_serial_number()) .serial_number(random_serial_number())
.not_valid_before(not_before) .not_valid_before(not_before)
.not_valid_after(not_before + datetime.timedelta(days=days)) .not_valid_after(not_before + datetime.timedelta(days=days))
.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=False) .add_extension(BasicConstraints(ca=False, path_length=None), critical=False)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(public_key), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(extended_key_usage, critical=False) .add_extension(extended_key_usage, critical=False)
.add_extension(self.create_x509_crldp(), critical=False) .add_extension(self.create_x509_crldp(), critical=False)
.sign(self.issuer_key, hashes.SHA256()) .sign(self.issuer_key, SHA256())
) )
# Write PEM file and attach intermediate certificate # Write PEM file and attach intermediate certificate
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem") file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(cert.public_bytes(encoding=Encoding.PEM))
file.write(self.issuer_cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(self.issuer_cert.public_bytes(encoding=Encoding.PEM))
return cert return cert
def revoke_cert(self, serial_number, file_name) -> None: def revoke_cert(self, serial_number, file_name) -> None:
"""Revoke a certificate""" """Revoke a certificate"""
revoked = ( revoked = (
x509.RevokedCertificateBuilder() RevokedCertificateBuilder()
.serial_number(serial_number) .serial_number(serial_number)
.revocation_date(date_20190101) .revocation_date(date_20190101)
.add_extension(x509.CRLReason(x509.ReasonFlags.superseded), critical=False) .add_extension(CRLReason(ReasonFlags.superseded), critical=False)
.build() .build()
) )
# Generate CRL # Generate CRL
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
) )
crl = ( crl = (
x509.CertificateRevocationListBuilder() CertificateRevocationListBuilder()
.issuer_name(self.issuer_cert.subject) .issuer_name(self.issuer_cert.subject)
.last_update(date_20190101) .last_update(date_20190101)
.next_update(date_20190101 + datetime.timedelta(days=7300)) .next_update(date_20190101 + datetime.timedelta(days=7300))
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(x509.CRLNumber(4097), critical=False) .add_extension(CRLNumber(4097), critical=False)
.add_revoked_certificate(revoked) .add_revoked_certificate(revoked)
.sign(self.issuer_key, hashes.SHA256()) .sign(self.issuer_key, SHA256())
) )
# Write CRL file # Write CRL file
file_path = os.path.join(CERTS_PATH, file_name + ".pem") file_path = os.path.join(CERTS_PATH, file_name + ".pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(crl.public_bytes(encoding=serialization.Encoding.PEM)) file.write(crl.public_bytes(encoding=Encoding.PEM))
file_path = os.path.join(CERTS_PATH, file_name + ".der") file_path = os.path.join(CERTS_PATH, file_name + ".der")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(crl.public_bytes(encoding=serialization.Encoding.DER)) file.write(crl.public_bytes(encoding=Encoding.DER))
class LeafCACertificate(Certificate): class LeafCACertificate(LeafCertificate):
"""Base class for a leaf certificate""" """Base class for a leaf certificate"""
def __init__(self, issuer_cert, issuer_key, common, cdp_port): def __init__(self, issuer_cert, issuer_key, common, cdp_port):
super().__init__(issuer_cert, issuer_key, "CSP", common, cdp_port, "intermediateCA") super().__init__(issuer_cert, issuer_key, "CSP", common, cdp_port, "intermediateCA")
class LeafTSACertificate(Certificate): class LeafTSACertificate(LeafCertificate):
"""Base class for a TSA leaf certificate""" """Base class for a TSA leaf certificate"""
def __init__(self, issuer_cert, issuer_key, common, cdp_port): def __init__(self, issuer_cert, issuer_key, common, cdp_port):
@ -364,40 +413,40 @@ class LeafTSACertificate(Certificate):
self.common_name = common self.common_name = common
super().__init__(issuer_cert, issuer_key, "Timestamp Root CA", common, cdp_port, "TSACA") super().__init__(issuer_cert, issuer_key, "Timestamp Root CA", common, cdp_port, "TSACA")
def make_cert(self, public_key, not_before, days) -> x509.Certificate: def make_cert(self, public_key, not_before, days) -> Certificate:
"""Generate a TSA leaf certificate""" """Generate a TSA leaf certificate"""
authority_key = x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier( authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
self.issuer_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier).value self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
) )
# The TSA signing certificate must have exactly one extended key usage # The TSA signing certificate must have exactly one extended key usage
# assigned to it: timeStamping. The extended key usage must also be critical, # assigned to it: timeStamping. The extended key usage must also be critical,
# otherwise the certificate is going to be refused. # otherwise the certificate is going to be refused.
extended_key_usage = x509.ExtendedKeyUsage( extended_key_usage = ExtendedKeyUsage(
[x509.oid.ExtendedKeyUsageOID.TIME_STAMPING] [ExtendedKeyUsageOID.TIME_STAMPING]
) )
cert = ( cert = (
x509.CertificateBuilder() CertificateBuilder()
.subject_name(self.create_x509_name(self.common_name)) .subject_name(self.create_x509_name(self.common_name))
.issuer_name(self.issuer_cert.subject) .issuer_name(self.issuer_cert.subject)
.public_key(public_key) .public_key(public_key)
.serial_number(x509.random_serial_number()) .serial_number(random_serial_number())
.not_valid_before(not_before) .not_valid_before(not_before)
.not_valid_after(not_before + datetime.timedelta(days=days)) .not_valid_after(not_before + datetime.timedelta(days=days))
.add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True) .add_extension(BasicConstraints(ca=False, path_length=None), critical=True)
.add_extension(x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False) .add_extension(SubjectKeyIdentifier.from_public_key(public_key), critical=False)
.add_extension(authority_key, critical=False) .add_extension(authority_key, critical=False)
.add_extension(extended_key_usage, critical=True) .add_extension(extended_key_usage, critical=True)
.add_extension(self.create_x509_crldp(), critical=False) .add_extension(self.create_x509_crldp(), critical=False)
.add_extension(self.create_x509_name_constraints(), critical=False) .add_extension(self.create_x509_name_constraints(), critical=False)
.sign(self.issuer_key, hashes.SHA256()) .sign(self.issuer_key, SHA256())
) )
# Write PEM file and attach intermediate certificate # Write PEM file and attach intermediate certificate
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem") file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(cert.public_bytes(encoding=Encoding.PEM))
file.write(self.issuer_cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(self.issuer_cert.public_bytes(encoding=Encoding.PEM))
return cert return cert
@ -433,7 +482,7 @@ class CertificateMaker():
issuer_cert, issuer_key = intermediate.make_cert() issuer_cert, issuer_key = intermediate.make_cert()
# Generate private RSA key # Generate private RSA key
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) private_key = generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key() public_key = private_key.public_key()
root.write_key(key=private_key, file_name="key") root.write_key(key=private_key, file_name="key")
@ -460,7 +509,7 @@ class CertificateMaker():
# Write DER file and attach intermediate certificate # Write DER file and attach intermediate certificate
file_path = os.path.join(CERTS_PATH, "cert.der") file_path = os.path.join(CERTS_PATH, "cert.der")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(cert.public_bytes(encoding=serialization.Encoding.DER)) file.write(cert.public_bytes(encoding=Encoding.DER))
def make_tsa_certs(self): def make_tsa_certs(self):
"""Make test TSA certificates""" """Make test TSA certificates"""
@ -470,7 +519,7 @@ class CertificateMaker():
issuer_cert, issuer_key = root.make_cert() issuer_cert, issuer_key = root.make_cert()
# Generate private RSA key # Generate private RSA key
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) private_key = generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key() public_key = private_key.public_key()
root.write_key(key=private_key, file_name="TSA") root.write_key(key=private_key, file_name="TSA")
@ -486,8 +535,8 @@ class CertificateMaker():
# Save the chain to be included in the TSA response # Save the chain to be included in the TSA response
file_path = os.path.join(CERTS_PATH, "tsa-chain.pem") file_path = os.path.join(CERTS_PATH, "tsa-chain.pem")
with open(file_path, mode="wb") as file: with open(file_path, mode="wb") as file:
file.write(cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(cert.public_bytes(encoding=Encoding.PEM))
file.write(issuer_cert.public_bytes(encoding=serialization.Encoding.PEM)) file.write(issuer_cert.public_bytes(encoding=Encoding.PEM))
def write_pkcs12_container(self, cert, key, issuer) -> None: def write_pkcs12_container(self, cert, key, issuer) -> None:
@ -499,16 +548,16 @@ class CertificateMaker():
# and private key encryption: DES-EDE3-CBC (vel 3DES_CBC) # and private key encryption: DES-EDE3-CBC (vel 3DES_CBC)
# pylint: disable=no-member # pylint: disable=no-member
encryption = ( encryption = (
serialization.PrivateFormat.PKCS12.encryption_builder() PrivateFormat.PKCS12.encryption_builder()
.key_cert_algorithm(serialization.pkcs12.PBES.PBESv1SHA1And3KeyTripleDESCBC) .key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC)
.kdf_rounds(5000) .kdf_rounds(5000)
.build(PASSWORD.encode()) .build(PASSWORD.encode())
) )
else: else:
encryption = serialization.BestAvailableEncryption(PASSWORD.encode()) encryption = BestAvailableEncryption(PASSWORD.encode())
# Generate PKCS#12 struct # Generate PKCS#12 struct
pkcs12 = serialization.pkcs12.serialize_key_and_certificates( pkcs12 = serialize_key_and_certificates(
name=b'certificate', name=b'certificate',
key=key, key=key,
cert=cert, cert=cert,