remove .SIG, switch back to Python.cryptography

master
Volker Birk 11 months ago
parent 0cba7826d6
commit d71f5cab67

1
.gitignore vendored

@ -190,3 +190,4 @@ test/*.pem
test/DIST.*
test/_DIST.*
test/PER_*
test/*.ppk

@ -5,7 +5,6 @@ files in its main directory:
- distribution archive in a file named DIST.A
- distribution key in a file named DIST.KEY
- distribution signature in a file named DIST.SIG
To use a signedpkg the user needs:
@ -40,11 +39,6 @@ The distribution key is the AES<256> key, with which the distribution archive
is encrypted using GCM<AES>. DIST.KEY contains the distribution key encrypted
with the provisioning key using RSA-OAEP.
## distribution signature
The distribution signature is the PKCS v1.5 RSASS<PSS, SHA256> detached
signature of the distribution archive file DIST.A using the deployment key.
## deployment key
The deployment key is an RSA keypair stored in a private key part and a BER

@ -90,7 +90,6 @@ namespace SignedPackage {
)
{
std::string cwd = std::filesystem::current_path();
std::filesystem::current_path(target_path);
struct archive *a = ::archive_read_new();
@ -103,6 +102,8 @@ namespace SignedPackage {
throw_archive_read_error(a);
}
std::filesystem::current_path(target_path);
struct ::archive_entry *entry;
int n = 0;
while (::archive_read_next_header(a, &entry) == ARCHIVE_OK) {
@ -145,29 +146,6 @@ namespace SignedPackage {
std::filesystem::current_path(cwd);
}
void check_signature(
std::filesystem::path file,
std::filesystem::path sig,
CryptoPP::PublicKey& key
)
{
CryptoPP::RSASS<CryptoPP::PSS, CryptoPP::SHA256>::Verifier verifier(key);
CryptoPP::SignatureVerificationFilter verificationFilter(verifier,
nullptr,
CryptoPP::SignatureVerificationFilter::SIGNATURE_AT_BEGIN
| CryptoPP::SignatureVerificationFilter::THROW_EXCEPTION);
CryptoPP::FileSource fileSource(((std::string) file).c_str(), false,
new CryptoPP::Redirector(verificationFilter));
CryptoPP::FileSource signatureSource(((std::string) sig).c_str(), false,
new CryptoPP::Redirector(verificationFilter));
signatureSource.PumpAll();
fileSource.PumpAll();
}
std::string decrypt_distribution_key(
std::filesystem::path key_path,
CryptoPP::PrivateKey& provisioning_key
@ -195,10 +173,10 @@ namespace SignedPackage {
provisioning_key);
std::ifstream ifs(archive, std::ios_base::binary | std::ios_base::in);
char iv[CryptoPP::AES::BLOCKSIZE];
char iv[12]; // 96 bit is GCM standard size
ifs.read(iv, sizeof(iv));
CryptoPP::EAX< CryptoPP::AES >::Decryption dec;
CryptoPP::GCM< CryptoPP::AES >::Decryption dec;
dec.SetKeyWithIV((const unsigned char*) distribution_key.c_str(),
distribution_key.size(), (const unsigned char*) iv, sizeof(iv));
@ -219,10 +197,7 @@ namespace SignedPackage {
{
std::filesystem::path target_path = mktempdir();
extract_archive(pkg_path, target_path, { "DIST.A", "DIST.KEY",
"DIST.SIG" });
check_signature(target_path / "DIST.A", target_path / "DIST.SIG",
deployment_key);
extract_archive(pkg_path, target_path, { "DIST.A", "DIST.KEY" });
decrypt_distribution_archive(target_path / "DIST.A",
target_path / "DIST.KEY", provisioning_key);

@ -23,12 +23,6 @@ namespace SignedPackage {
std::vector< std::string > filenames = { }
);
void check_signature(
std::filesystem::path file,
std::filesystem::path sig,
CryptoPP::PublicKey& key
);
void decrypt_archive(
std::filesystem::path archive,
std::filesystem::path key,
@ -49,7 +43,7 @@ namespace SignedPackage {
std::filesystem::path extract_deployment_archive(
CryptoPP::PublicKey& deployment_key,
CryptoPP::PrivateKey& provisioning_key,
std::string pkg_path
std::filesystem::path pkg_path
);
void install_if_location_empty(

@ -45,8 +45,9 @@ clean:
rm -f $(TESTS)
rm -Rf *.testdata
rm -Rf *.pem *.der
rm -f DIST.* _DIST.*
rm -f DIST.*
rm -Rf PER_USER_DIRECTORY
rm -f *.ppk
test_%: test_%.o $(TARGET)
$(CXX) $(LDFLAGS) $< $(TARGET) -o $@

@ -18,10 +18,13 @@ gen_keypair provisioning_key
mkdir PER_USER_DIRECTORY
echo content > PER_USER_DIRECTORY/testfile.testdata
zip -r _DIST.AD PER_USER_DIRECTORY
zip -r DIST.AD PER_USER_DIRECTORY
# generate distribution key encrypted with provisioning key and encrypt
# distribution archive
../utils/encrypt_distribution_archive.py
# gen sample package
zip pEp.ppk DIST.A DIST.KEY

@ -1,14 +1,39 @@
#include <iostream>
#include "../src/unpack.hh"
#include <cryptopp/files.h>
void Load(const std::string& filename, CryptoPP::BufferedTransformation& bt)
{
CryptoPP::FileSource file(filename.c_str(), true);
file.TransferTo(bt);
bt.MessageEnd();
}
void LoadPublicKey(const std::string& filename, CryptoPP::PublicKey& key)
{
CryptoPP::ByteQueue queue;
Load(filename, queue);
key.Load(queue);
}
void LoadPrivateKey(const std::string& filename, CryptoPP::PrivateKey& key)
{
CryptoPP::ByteQueue queue;
Load(filename, queue);
key.Load(queue);
}
void test_extract_archive()
{
std::cout << "\n*** test: extract_archive()\n\n";
SignedPackage::extract_archive("_DIST.AD", ".");
std::cout << "works: _DIST.AD extracted\n";
SignedPackage::extract_archive("DIST.AD", ".");
std::cout << "works: DIST.AD extracted\n";
SignedPackage::extract_archive("_DIST.AD", ".", { "PER_USER_DIRECTORY/testfile.testdata" });
SignedPackage::extract_archive("DIST.AD", ".", { "PER_USER_DIRECTORY/testfile.testdata" });
std::cout << "works: file archive_file1.testdata extracted\n";
try {
@ -20,7 +45,7 @@ void test_extract_archive()
}
try {
SignedPackage::extract_archive("_DIST.AD", "notexist");
SignedPackage::extract_archive("DIST.AD", "notexist");
throw std::runtime_error("notexist is not a valid path");
}
catch (std::exception& e) {
@ -28,15 +53,46 @@ void test_extract_archive()
}
}
void test_check_signature()
void test_decrypt_distribution_key()
{
std::cout << "\n*** test: decrypt_distribution_key()\n\n";
CryptoPP::RSA::PrivateKey provisioning_key;
LoadPrivateKey("provisioning_key.der", provisioning_key);
SignedPackage::decrypt_distribution_key("DIST.KEY", provisioning_key);
}
void test_decrypt_distribution_archive()
{
std::cout << "\n*** test: decrypt_distribution_archive()\n\n";
CryptoPP::RSA::PrivateKey provisioning_key;
LoadPrivateKey("provisioning_key.der", provisioning_key);
SignedPackage::decrypt_distribution_archive("DIST.A", "DIST.KEY", provisioning_key);
}
void test_extract_deployment_archive()
{
std::cout << "\n*** test: extract_deployment_archive()\n\n";
CryptoPP::RSA::PublicKey deployment_key;
LoadPublicKey("deployment_key-pub.der", deployment_key);
CryptoPP::RSA::PrivateKey provisioning_key;
LoadPrivateKey("provisioning_key.der", provisioning_key);
std::string path = SignedPackage::extract_deployment_archive(deployment_key, provisioning_key, "pEp.ppk");
std::cout << "\nextraced to " << path << "\n";
}
int main()
{
test_extract_archive();
test_check_signature();
test_decrypt_distribution_key();
test_decrypt_distribution_archive();
test_extract_deployment_archive();
return 0;
}

@ -3,12 +3,11 @@
import argparse
import os
from Crypto.Signature import pss
from Crypto.Hash import SHA256
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
parser = argparse.ArgumentParser(description='encrypt distribution archive'
' using provisioning key to encrypt and deployment key to sign')
@ -22,38 +21,34 @@ parser.add_argument('--passphrase', default=None,
parser.add_argument('--provisioning-key', default='provisioning_key-pub.der',
help='file with public key part of provisioning key in DER format')
parser.add_argument('--distribution-archive', default='_DIST.AD',
parser.add_argument('--distribution-archive', default='DIST.AD',
help='unencrypted version of distribution archive file, usually in ZIP format')
args = parser.parse_args()
with open(args.deployment_key, 'rb') as keyfile:
deployment_key = RSA.import_key(keyfile.read(), passphrase=args.passphrase)
with open(args.deployment_key, "rb") as deployment_key_file:
deployment_key = serialization.load_der_private_key(deployment_key_file.read(), password=args.passphrase)
with open(args.provisioning_key, 'rb') as keyfile:
provisioning_key = RSA.import_key(keyfile.read())
with open(args.provisioning_key, "rb") as provisioning_key_file:
provisioning_key = serialization.load_der_public_key(provisioning_key_file.read())
distribution_key = get_random_bytes(32)
distribution_key = AESGCM.generate_key(bit_length=256)
oaep = PKCS1_OAEP.new(provisioning_key)
encrypted_distribution_key = provisioning_key.encrypt(distribution_key,
padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(), label=None))
with open('DIST.KEY', 'wb') as keyfile:
keyfile.write(oaep.encrypt(distribution_key))
with open('DIST.KEY', 'wb') as distribution_key_file:
distribution_key_file.write(encrypted_distribution_key)
with open('_DIST.AD', 'rb') as unencrypted_archive:
# FIXME: this consumes a lot of RAM
unencrypted_content = unencrypted_archive.read()
with open(args.distribution_archive, 'rb') as distribution_archive_file:
distribution_archive = distribution_archive_file.read()
nonce = get_random_bytes(12)
aes_gcm = AES.new(distribution_key, AES.MODE_GCM, nonce=nonce)
aesgcm = AESGCM(distribution_key)
nonce = os.urandom(12)
encrypted_archive = aesgcm.encrypt(nonce, distribution_archive, None)
distribution_archive = None
ciphertext, tag = aes_gcm.encrypt_and_digest(unencrypted_content)
with open('DIST.A', 'wb') as distribution_archive:
distribution_archive.write(ciphertext)
hash = SHA256.new(ciphertext)
signature = pss.new(deployment_key).sign(hash)
with open('DIST.SIG', 'wb') as distribution_signature:
distribution_signature.write(signature)
with open('DIST.A', 'wb') as encrypted_archive_file:
encrypted_archive_file.write(nonce)
encrypted_archive_file.write(encrypted_archive)

@ -1 +1 @@
pycryptodome
cryptography

Loading…
Cancel
Save