I'm developing a WebService client in C++ for "Electronic Invoice" in Argentina. The webservice client and the xml treatment is not a problem but the cryptographic part give some headache (I'm quite new in this topic).
I'm reading the Botan documentation and found an example somewhat similar to what I need but I'm having difficulties adapting it.
I need to encrypt the XML in SHA1+RSA using the certificates and encode the result in Base64.
The official documentation provide examples in many languages unfortunately C++ is not one of them, I use the php example as start point to create my PoC code in C++.
The exact problem is this.
I have this XML example:
<loginTicketRequest version="1.0"><header><uniqueId>1560949868</uniqueId><generationTime>2019-06-19T10:10:08-03:00</generationTime><expirationTime>2019-06-19T10:12:08-03:00</expirationTime></header><service>wsfe</service></loginTicketRequest>
this XML became in this Base64 string
MIIHDgYJKoZIhvcNAQcCoIIG/zCCBvsCAQExDzANBglghkgBZQMEAgEFADCCAS8G
CSqGSIb3DQEHAaCCASAEggEcPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
VVRGLTgiPz4NCjxsb2dpblRpY2tldFJlcXVlc3QgdmVyc2lvbj0iMS4wIj48aGVh
ZGVyPjx1bmlxdWVJZD4xNTYwOTQ5ODY4PC91bmlxdWVJZD48Z2VuZXJhdGlvblRp
bWU+MjAxOS0wNi0xOVQxMDoxMDowOC0wMzowMDwvZ2VuZXJhdGlvblRpbWU+PGV4
cGlyYXRpb25UaW1lPjIwMTktMDYtMTlUMTA6MTI6MDgtMDM6MDA8L2V4cGlyYXRp
b25UaW1lPjwvaGVhZGVyPjxzZXJ2aWNlPndzZmU8L3NlcnZpY2U+PC9sb2dpblRp
Y2tldFJlcXVlc3Q+DQqgggPMMIIDyDCCArCgAwIBAgIISL4VMzAJIDswDQYJKoZI
hvcNAQEFBQAwQzElMCMGA1UEAwwcQUZJUCBUZXN0aW5nIENvbXB1dGFkb3JlcyBD
QTENMAsGA1UECgwEQUZJUDELMAkGA1UEBhMCQVIwHhcNMTQxMDE2MTk0NTA2WhcN
MTcwNzEyMTk0NTA2WjBmMRkwFwYDVQQDDBBNYXJpYW5vIFJlaW5nYXJ0MRkwFwYD
VQQFExBDVUlUIDIwMjY3NTY1MzkzMSEwHwYDVQQKDBhQeUFmaXBXcy1TaXN0ZW1h
cyBBZ2lsZXMxCzAJBgNVBAYTAkFSMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQCa+TDQaSgL1/wcMzFJXi1ipc2VurFOx4LlP13pIrC0hX2xP+I+qNeD2vZlaiA0
bMAZfx6w/+KjOPsJaQXre+TC6NU7Ed7FV6GZO6a2ZM/KjkoJSJIG/aVn+jljOkkl
2ANiTghi9tT3hPK1k6KQz6X2uBHaInKMrvi2Cj9/Tvi6UQIDAQABo4IBHzCCARsw
DAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0OBBYEFJ61KivCQwKv
/FnE6OJhBgz4nzjsMB8GA1UdIwQYMBaAFER07rScJt9W4cEN61cLkBk2PZYBMIG6
BgNVHSAEgbIwga8wgawGDisGAQQBgbtjAQIBAgEBMIGZMIGWBggrBgEFBQcCAjCB
iR6BhgBDAGUAcgB0AGkAZgBpAGMAYQBkAG8AIABwAGEAcgBhACAAYwBvAG0AcAB1
AHQAYQBkAG8AcgBlAHMAIABzAG8AbABvACAAdgBhAGwAaQBkAG8AIABlAG4AIABl
AG4AdABvAHIAbgBvAHMAIABkAGUAIABkAGUAcwBhAHIAcgBvAGwAbABvMA0GCSqG
SIb3DQEBBQUAA4IBAQCM/PmA6htlY/X8XK98XOtQxjOaLt5MgFdGiwyop13Xyh3n
c9ak4KFP6qbz6gKzCelkYoPgFLreP+lvL62EYrNaLacNLZUbko7wZotjRRxZo0+f
OkjJMIafgM5mycdVvcI1uzIKPWba5F5w8NawcL8bloSqDWX1dJRwvhs2hmcN3iIf
aYosbVUI/DMLys1xFqCMSBrTX4xtfL82TOg+mSVaRW37aED8ta7jTcBTn+001nos
c/1rXrB0qBQa7EKD7VJKSLkn4RV/HwO8R1POVexyrk7TzNeamcQMIKjkhHzXSsOb
BROqptCxUDh4QUdLQNRtwsJClufr6Bgidg37JK+4MYIB4DCCAdwCAQEwTzBDMSUw
IwYDVQQDDBxBRklQIFRlc3RpbmcgQ29tcHV0YWRvcmVzIENBMQ0wCwYDVQQKDARB
RklQMQswCQYDVQQGEwJBUgIISL4VMzAJIDswDQYJYIZIAWUDBAIBBQCggeQwGAYJ
KoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkwNjE5MTMx
MTA4WjAvBgkqhkiG9w0BCQQxIgQgPhDZEOopRNlv7JVKSyLZ2AWdNb81O6zm3hgM
BADUI34weQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJYIZIAWUDBAEW
MAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgICAIAwDQYIKoZI
hvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcNAQEBBQAE
gYAaqEV7X2WqmODhoqV64aLmM1mkUuVsGxgBDc09IRwUtD6wQAoMd87iIVeQ0n2X
qHHjmAz8QLp5tCApSPLjdaXbzufJ6vfOhpuHzu2QuOZh7AM9g8+zLubcs/+aRGC8
RUXoVaHajVOeHN4iR5pIJ3n2zuIWgowyK1sH3Q33i0A+MQ==
using this PHP function
$STATUS=openssl_pkcs7_sign("TRA.xml", "TRA.tmp", "file://".CERT,
array("file://".PRIVATEKEY, PASSPHRASE),
array(),
!PKCS7_DETACHED
);
Where CERT and PRIVATEKEY are the public and private keys, PASSPHRASE is an empty string and the file TRA.xml contains the XML example provided above.
You can download the public and private key from this link
Example Certificates
Botan Example in C++
#include <botan/pkcs8.h>
#include <botan/hex.h>
#include <botan/pk_keys.h>
#include <botan/pubkey.h>
#include <botan/auto_rng.h>
#include <botan/rng.h>
#include <iostream>
int main (intargc,char*argv[])
{
if(argc!=2)
return1;
std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's.");
std::vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
std::unique_ptr<Botan::RandomNumberGenerator> rng(newBotan::AutoSeeded_RNG);
//load keypair
std::unique_ptr<Botan::Private_Key> kp(Botan::PKCS8::load_key(argv[1],*rng.get()));
//encrypt with pk
Botan::PK_Encryptor_EME enc(*kp,*rng.get(), "EME1(SHA-256)");
std::vector<uint8_t> ct = enc.encrypt(pt,*rng.get());
//decrypt with sk
Botan::PK_Decryptor_EME dec(*kp,*rng.get(), "EME1(SHA-256)");
std::cout << std::endl << "enc: " << Botan::hex_encode(ct) << std::endl << "dec: "<< Botan::hex_encode(dec.decrypt(ct));
return 0; //Edited :D, Thanks jww
}
I need to encrypt the XML in SHA1+RSA using the certificates and encode the result in Base64. Any help will be very appreciated.
I'm a little bit confused about your main question. Guess you have to mention it more obvious. But as I noticed the problem is how to encrypt using your public RSA key and SHA-1 hash function! (Am I right?)
So in that case I would say the EME1(SHA-256) that you could see in encryptor/decryptor objects aren't the bulk encryption algorithm and hash function used for encryption. They are padding algorithms!
In Botan there are tls_channel and tls_callbacks which handle the whole process of encryption and decryption between two sides. Take a further look at them.
Also if Botan is not mandatory I suggest you to use Openssl in evp.h file the function EVP_SealInit will may help you by letting pick your desired algorithm with const EVP_CIPHER *type input. For more info check this link
Related
I'm trying to figure out how to generate and use an RSA key with Crypto++. To be precise, I am being asked to:
You will implement secure communications between two parties, Alice and
Bob.
For simplicity, the sending of a message from the sender to the receiver will be simulated
through writing the message into a file by the sender and reading the message
from the file by the receiver.
This assignment is designed to practice key distribution, encryption/decryption,
and integrity protection
with secret key cryptography and public key cryptography.
Communication scenario: Alice (as a Client) needs to send messages to Bob (as a Server). Alice and Bob each have
a pair of under the RSA cryptosystem
(their key
pairs are different), and they know each other’s public key beforehand
(the public keys can be hard coded into the program
or read from a file). Step 1: Set
up a shared secret key: Alice and Bob set up a shared secret key using the following
method: Alice generates
a random key k, encrypts it using Bob’s public key with the RSA
algorithm, and sends the ciphertext to Bob. Bob receives the ciphertext and then decrypts it
to get the key k.
So, I've spent a few hours trying to set this up properly, and it seems like I've finally gotten Eclipse to accept the Crypto++ library itself, as it has compiled up to this point. Here is the complete code I have so far:
#include <iostream>
#include "cryptlib.h"
#include <rsa.h>
#include <osrng.h>
#include <base64.h>
#include <files.h>
using namespace CryptoPP;
int main()
{
std::cout << "!!!Hello World!!!" << std::endl; // prints !!!Hello World!!!
// InvertibleRSAFunction is used directly only because the private key
// won't actually be used to perform any cryptographic operation;
// otherwise, an appropriate typedef'ed type from rsa.h would have been used.
AutoSeededRandomPool rng;
InvertibleRSAFunction privkey;
privkey.Initialize(rng, 1024); <--
// With the current version of Crypto++, MessageEnd() needs to be called
// explicitly because Base64Encoder doesn't flush its buffer on destruction.
Base64Encoder privkeysink(new FileSink("c:\\privkey.txt"));
privkey.DEREncode(privkeysink);
privkeysink.MessageEnd();
// Suppose we want to store the public key separately,
// possibly because we will be sending the public key to a third party.
RSAFunction pubkey(privkey);
Base64Encoder pubkeysink(new FileSink("c:\\pubkey.txt"));
pubkey.DEREncode(pubkeysink); <--
pubkeysink.MessageEnd();
return 0;
}
Some of this I have pulled from here in an attempt to understand exactly how this library works:
https://www.cryptopp.com/wiki/User_Guide:_rsa.h
(We were given no sort of primer, and I find the site a little confusing)
The current issue I'm having at the moment is that the two lines I've marked with '<--' do not compile.
Specifically:
undefined reference to CryptoPP::InvertibleRSAFunction::Initialize(CryptoPP::RandomNumberGenerator&, unsigned int, CryptoPP::Integer const&)
undefined reference to CryptoPP::X509PublicKey::DEREncode(CryptoPP::BufferedTransformation&) const
I would ask what I would need to do to make these two compile, but I'm not even sure this sample code even does what I want it to. How would I generate the keys I need for this?
I am trying to RSA public key decrypt a signed file using wolfcrypt - yes, I may or may not be abusing the "sign/verify" power of RSA to encrypt a separate AES key using the private key and decrypt using the public key.
Unfortunately, I am stuck at wc_RsaSSL_Verify() - for the life of me I can't figure out why it is returning BAD_FUNC_ARG - I figured an error like that should be immediately visible to somebody else so I'm deciding to call upon the collective powers of StackOverflow.
As far as I can tell, I'm giving the function what it's asking for - an input buffer, an output buffer, the size of each, and a pointer to the RsaKey struct. Here is a code snippet from the function in question:
bool VerifyWorker::GetAESKey()
{
bool result = true;
uint8_t en_aes_file_buff[VerifyWorkerLocal::RSA_KEY_SIZE];
uint8_t de_aes_file_buff[VerifyWorkerLocal::RSA_KEY_SIZE];
uint8_t* aes_iv_ptr = NULL;
// keyfile filestream
std::fstream aes_file;
// rsa_key must be initialized
if(rsa_key == NULL)
{
result = false;
}
// Open the key file and read it into a local buffer, then decrypt it and use it to initialize the
// aes struct
if(result)
{
aes_file.open(this->aes_key_file, std::ios_base::in | std::ios_base::binary);
if(aes_file.fail())
{
// Unable to open file - perror?
perror("GetAESKey");
result = false;
}
else
{
aes_file.read(reinterpret_cast<char*>(en_aes_file_buff), VerifyWorkerLocal::RSA_KEY_SIZE + 1);
if(!aes_file.eof())
{
// we didn't have enough space to read the whole signature!
std::cerr << "aes_file read failed! " << aes_file.rdstate() << std::endl;
result = false;
}
}
}
// "Unsign" the aes key file with RSA verify, and load the aes struct with the result
if(result)
{
int wc_ret = 0;
wc_ret = wc_RsaSSL_Verify(const_cast<const byte*>(en_aes_file_buff),
VerifyWorkerLocal::RSA_KEY_SIZE, reinterpret_cast<byte*>(&de_aes_file_buff),
VerifyWorkerLocal::RSA_KEY_SIZE, rsa_key);
The rsa_key is a private member initialized (successfully, using wc_PublicKeyDecode()) in a separate function with a public key DER file. I generated both the public and private key using OpenSSL - which should properly pad my AES key and iv file using PKCS#1 v1.5 b default.
I should also mention that I am using wolfssl version 3.9.8. Thanks!
The issue, I found, was that the file that I had signed with my RSA key was not signed correctly. When I signed the file using OpenSSL, my cli invocation was
openssl rsautl -in keyfile -out keyfile -inkey private.pem -sign
Apparently, openssl does not like you to specify the same file for -in and -out. When I changed it to something like
openssl rsautl -in keyfile -out keyfile_signed -inkey private.pem -sign
I was actually able to verify the file using wc_RsaSSL_Verify.
So, like most stupid late-night, last hour software problems, I was looking in the wrong place entirely. I was a bit thrown off by the BAD_FUNC_ARG being returned and thought that it had to do explicitly with the format of the function arguments, not necessarily their content. Hopefully this answer is useful for somebody else, too.
It sounds like you are trying to use RSA_Sign to perform an "Encrypt" of an AES key. Then I assume you are sending to a remote partner or computer who will then run an RSA_Verify operation to decrypt the AES key do I understand the scenario correctly?
If so I apologize it did not show up if you searched on how to do this initially but we actually have an example of doing exactly that here:
https://github.com/wolfSSL/wolfssl-examples/tree/master/signature/encryption-through-signing
That example includes two separate applications. The first app, "rsa-private-encrypt-app.c", will sign (encrypt) the "fake Aes Key" and output the result to a file. The second app, "rsa-public-decrypt-app.c", then opens the file that was output and does a verify (decrypt) on the data contained in the file to recover the original "fake Aes Key".
I may or may not be abusing the "sign/verify" power of RSA to encrypt a separate AES key using the private key and decrypt using the public key.
No not at all, that is a valid use of RSA sign/verify ASSUMING you are working with fixed-length inputs such as an AES key.
That's why we created the example! We actually had a user ask a very similar question on our forums awhile back which led to us making the example.
One thing to make note of though on the issues you encountered with openssl and wolfssl is actually talked about in the README:
https://github.com/wolfSSL/wolfssl-examples/blob/master/signature/encryption-through-signing/README.md
... Keep in mind this is not a TRUE RSA ENCRYPT and will likely not inter-op with other libraries that offer a RSA_PRIVATE_ENCRYPT type API.
This is a true SIGN operation.
If you have any other questions feel free to post them here (and add the wolfssl tag of course) or you can also send us an email anytime at support#wolfssl.com
Disclaimer: I work for wolfSSL Inc.
I want to license my software using RSA encryption. My software has several executables and I plan to have each check the signature of a common license file before they proceed to do what it is they do. My goal is not to make it impossible to circumvent the licensing protection, just make it very difficult. I know that no one can make it impossible.
The executables currently run in a Windows environment, but they will only be released to work in a Linux environment.
My current plan is to put the public key within each executable for signature verification. The programs already have a 'safe' encrypted area in which to put the key.
My question for this post is, does my implementation method make sense? Is there another alternative? The alternative to have the public key in a separate file would allow a hacker to replace that file and use their own license file and signature. That doesn't seem as safe.
Additionally I've been reading through the crypto++ documentation and running the example code to try and accomplish this task. I cannot get any code to work that puts the key into a non-file sink and back again. All the examples write and read to files. I need to be able to save and load from a string or a byte queue. A simple attempt to do this is below, but when it runs I get this error, when r2.BERDecodePrivateKey() executes:
Unhandled exception at 0x7630c41f in MyRSA.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x002ef32c..
#include <osrng.h>
#include "rsa.h"
using CryptoPP::RSA;
#include <queue.h>
using CryptoPP::ByteQueue;
int myCode_key2ByteQueueToKey(void)
{
////////////////////////////////////////////////////////////////////////
// Generate the keys
AutoSeededRandomPool rnd;
CryptoPP::RSA::PrivateKey r1;
r1.GenerateRandomWithKeySize(rnd, 2048);
CryptoPP::RSA::PublicKey rsaPublic(r1);
////////////////////////////////////////////////////////////////////////
// Put the 'inner' part of the key into a ByteQueue - whatever that is.
ByteQueue queue;
r1.DEREncodePublicKey(queue);
////////////////////////////////////////////////////////////////////////
// Copy the byte queued inner key into another key
CryptoPP::RSA::PrivateKey r2;
r2.BERDecodePrivateKey(queue, false /*optParams*/, queue.MaxRetrievable());
////////////////////////////////////////////////////////////////////////
// Validate the key made the trip in and out of a byte queue ok.
if(!r1.Validate(rnd, 3)) printf("Validation of oringal key failed.\n");
if(!r2.Validate(rnd, 3)) printf("Validation of reloaded key failed.\n");
if(r1.GetModulus() != r2.GetModulus() ||
r1.GetPublicExponent() != r2.GetPublicExponent() ||
r1.GetPrivateExponent() != r2.GetPrivateExponent())
{
printf("Key didn't survive round trip in and out of a byte queue.");
}
return 0;
}
I do not have a fix for the above code. There's something I don't understand about library and as a result something's missing, but I've got to get a move on.
I thought I'd post an alternative I've found. Its an example on the Crypto++ wiki that puts the keys into strings (and not files) and back again. The round trip is shown to work.
http://www.cryptopp.com/wiki/BERDecode
Instead of
CryptoPP::RSA::PrivateKey
it uses
CryptoPP::RSAES_OAEP_SHA_Decryptor
and similarly for the public key. This allows the use of a member function AccessKey() which isn't available for the PrivateKey class.
If anyone has a fix for the original code, I urge you to please post it as it would help me better understand this library.
So basically you do this:
Generate 2048 bits private key
Encode a public key in DER format from the exponents of your private key to your bytequeue
Try to decode it as a private key from the bytequeue <-- here is the error
Validate the key...
You cannot decode a public key to a private key, some encoding flags differs.
As for CryptoPP::RSAES_OAEP_SHA_Decryptor
it's a good practice to use it for key generation as it is aware of safe primes.
It is also simpler to use for general decryption task as it includes everything you need in one object.
See http://www.cryptopp.com/wiki/Keys_and_Formats#High_Level_Objects
Hope it helped even it's a late answer ;)
Resolved (look for my answer). I need help encrypting a password with RSA in C++. I'm working for Blackberry10 in C++ and I've been looking for a RSA tutorial or something that walk me through the encrypting process but sadly I haven't found anything consistant.
I've been told that the process consist basicaly in three steps:
1)Generate the RSA public key with the module and exponent.
2)Encrypt the text with the public key.
3)Encrypt the text again in base640.
If you are wondering why I need to follow this three steps is because I'm working in a banking app, and those are their requirements.
I've been searching all over and I haven't found even how to make the first step, generate the public key with the module and the exponent (I already have both).
Any help will be appreciated.
Thanks.
Is not that I'm building the whole app by myself. We are a team and I need to encrypt just the client password with RSA and send it to the next step of the process. I do have experiencie working with Blackberry and RSA but in Java, where the process is a little bit easier, e.g: In java the first step once you got the module and public exponent is create the RSA Public Key Object through a very simple syntaxis: RSAPublicKey publicKey = new RSAPublicKey(new RSACryptoSystem(2048),ebytes, mbytes);. In this part is where I'm little bit lost because I haven't found the proper BB10 documentation. I'm sorry if I created the illusion that I'm creating a whole encryption API by myself. BB10 has this security API based in hursa.h (https://developer.blackberry.com/native/beta/reference/com.qnx.doc.crypto/topic/about_rsa_raw.html) I'm trying to implement it, but I haven't been successful. #owlstead #dajames #bta
I highly recommend that you take advantage of an existing encryption library to handle all of this for you. OpenSSL is widely used, and the LibTom libraries include an encryption lib as well. Encryption is not an easy thing to implement from scratch, and you will save a considerable amount of time and frustration by using an existing implementation. OpenSSL in particular is a good choice, as it has passed FIPS certification tests multiple times. Since you're working on a banking app, you (and your customers) will most likely want to use an implementation that has been certified.
Even if you insist on implementing your own encryption libraries from scratch, I encourage you to check out the aforementioned libraries as examples.
It seems to me that you know even less than you think you do about how this cryptography works.
One doesn't usually use RSA encryption to encrypt data. It can be done for something short like a PIN or password, but what is usually done is to generate a symmetric key and to encrypt the data with the symmetric key and then use RSA to encrypt the symmetric key.
If you are sending a password to a bank then what you are probably supposed to be doing is to use the RSA key supplied by the bank in their own key certificate. Only the bank has the private key, so only they can decrypt the password. If that's right then you don't need to generate an RSA key, but you do need to verify that the certificate is trusted.
I don't program Blackberries, so I don't know what cryptography APIs they support, but I would expect everything you need to be built-in. This is all pretty standard stuff.
I recommend that you start by reading up on public key cryptography (e.g. on Wikipedia here and here) before starting to design your solution.
Resolved. After doing some research and getting to know better with BB10 coding and RSA, I finally came out with the solution to successfuly encrypt a plain text with RSA and Base64 in C/C++ for BB10 or any other platform. Please take in consideration that I have the modulus and the public exponent of the rsa object from the services that I'm working with.
The code:
QByteArray answer;
RSA* rsa = RSA_new();
BIGNUM *modulus = BN_new();
BIGNUM *exponent = BN_new();
const char *modulusString = rsaObj->getM(); //My Modulus
const char *exponentString = rsaObj->getE(); //My exponent
BN_hex2bn(&modulus, modulusString);
BN_hex2bn(&exponent, exponentString);
rsa->n = BN_new();
BN_copy(rsa->n, modulus);
rsa->e = BN_new();
BN_copy(rsa->e, exponent);
int maxSize = RSA_size(rsa);
qDebug() << "maxSize:" << maxSize;
const char *inn = "1234";
unsigned char *encrypted = (unsigned char*) malloc(maxSize);
int bufferSize = RSA_public_encrypt(strlen(inn), (unsigned char *) inn,
encrypted, rsa, RSA_PKCS1_PADDING);
if (bufferSize == -1) {
RSA_free(rsa);
qDebug() << "Error";
}
QByteArray enc = QByteArray::fromRawData((const char*) encrypted, 256);
answer = enc.toBase64();
return answer;
Thanks and I expect this helps to the new BB10 developers
I need to be able to unzip some AES (WinZip) encrypted zip files from within some C/C++ code on Windows. Has anybody got a way to do this? I'm hoping for either some appropriate code or a DLL I can use (with an example usage). So far my searches have proved fruitless.
The commonly prescribed InfoZip libraries do not support AES encryption.
The best solution I have at the moment is calling the 7z.exe command line program from my program, but considering I'll be unzipping 100 files or so, this is less than ideal.
Here is the minizip zlib contribution with AES support for both encryption and decryption.
https://github.com/nmoinvaz/minizip
DotNetZip can do it. If you're not averse to using Managed C++.
From the DotNetZip documentation, this is the code to create an AES Encrypted zip file. (The code to extract is similar).
#include "stdafx.h"
using namespace System;
using namespace Ionic::Zip;
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Hello World");
ZipFile ^ zip;
try
{
zip = gcnew ZipFile();
zip->Password = "Harbinger";
zip->Encryption = EncryptionAlgorithm::WinZipAes128;
zip->AddEntry("Readme.txt", "This is the content for the Readme.txt entry.");
zip->Save("test.zip");
}
finally
{
zip->~ZipFile();
}
Console::WriteLine(L"Press <ENTER> to quit.");
Console::ReadLine();
return 0;
}
Also - I wrote DotNetZip so I have a certain amount of favoritism toward it! But I don't see what's wrong with exec'ing 7z.exe 100 times? Are you concerned about performance?
http://www.artpol-software.com/ZipArchive/ is the best choice.