How to load RSA key pair without Openssl or other Library - c++

CCFor a project I was searching for a simple RSA implementation to exchange a small secret via an unsecured but existing communication protocol. To keep it small and easy to portable to different platforms I did not want to link against OpenSSL or Crypto++. I found that as a part of the axTLS project which has a suitable license and an easy to extract RSA algorithm. The rsa function for encryption needs two components (as it usses the public key). The pup_exp is 65537 and modulus is the public part of the key and priv_exp the private one.
void RSA_priv_key_new(RSA_CTX **ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len,
const uint8_t *priv_exp, int priv_len
)
For easy use for the user, I want to load a certificate like X.509 or PEM generated by a library like OpenSSL, but in C or C++ code without including the whole OpenSSL stuff. But at the moment I even did not find an understandable documentation of the common key file formats.

There are two types of RSA public key format widely used and they are PKCS#1 and X.509(SubjectPublicKeyInfo).
I have used libtomcrypt(http://libtom.org/?page=features). It supports both the RSA key formats and very much portable. The license is non restrictive.

Related

How to send EVP_PKEY to other party?

I am struggling with the OpenSSL API for C++ at the moment. I'm using the EVP functions to generate a RSA keypair which then is used to encrypt the AES key that was used for encrypting the data (hybrid encryption).
Key generation:
EVP_PKEY* keypair = NULL;
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096);
EVP_PKEY_keygen(ctx, &keypair);
EVP_PKEY_CTX_free(ctx);
Now I have a keypair. When Encrypting a message on my own machine via EVP_SealInit / EVP_SealUpdate / EVP_SealFinal there is no problem. Same for the decrypting process. I simply give keypair as an argument to the SealInit / OpenInit function.
But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?
One way I found in the Internet is using PEM_write_bio_PUBKEY or PEM_write_bio_PrivateKey to convert the Keys to char*. When trying it seemed to work. But I'm still not 100% sure. So Please look at my code and tell me if those functions are the way to go:
unsigned char* publicKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, keypair);
RSAmakeString(&publicKey, bio);
unsigned char* privateKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bio, keypair, NULL, NULL, 0, 0, NULL);
RSAmakeString(&privateKey, bio);
The other thing is how do I convert the char* back to EVP_PKEY*? Are there any functions? Because if I want to use SealInit with my public Key on another computer I have to convert it back from a char* to an EVP_PKEY*, so I can use it in the function. Any suggestions?
But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?
You need something for serialization and wire formats or a presentation format. Your public key and encrypted messages will likely have 0 characters, which appear as embedded NULL. So you need to have both a buffer and explicit length .
Use Google's ProtocolBuffers, Binary JSON, or even ASN.1/DER encoding. I think Google's ProtocolBuffers are message oriented, so they won't return a message until the complete message is available.
You could also Hex, Base32 or Base64 encode it. But you still need to communicate a length so the receiving party knows they got the whole message. On a local LAN you will probably never experience a problem. Over the Internet you will probably get occasional failures as your perform short reads on occasion.
Your thoughts on PEM_write_bio_PUBKEY are effectively Base64 encoding the key, so it suffers the same potential problem as Hex, Base32 or Base64 encoding.
how do I convert the char* back to EVP_PKEY
Well, you probably won't be using a char* based on your changes above. Once you refine the design, you should probably ask a new question.
But at the moment, and given you saved the key with PEM_write_bio_PUBKEY and PEM_write_bio_PrivateKey, then you would use PEM_read_bio_PUBKEY or PEM_read_bio_PrivateKey, respectively. Also see OpenSSL's PEM man page.
Related to C++, here are some tricks when working with OpenSSL. If you are using C++11, then unique_ptr really makes it easy to work with some OpenSSL objects.
unique_ptr and OpenSSL's STACK_OF(X509)*
How to get PKCS7_sign result into a char * or std::string
Non-printable character after generating random n-byte Base64 string
EVP Symmetric Encryption and Decryption | C++ Programs on the OpenSSL wiki

Use PGP public key to cipher with Windows CryptoApi in C++

I don't know if this is possible at all. A pair of RSA keys are generated with GNUPG, and the public key is exported to a file. My program receives such file and then it has to encrypt some data with the public RSA key in that file. The program is written in C/C++ and it won't use external libraries, so all I can use is Windows CryptoApi functions (CryptStringToBinary, CryptDecodeObjectEx, CryptImportPublicKeyInfo, etc).
This method works with a public 2048 bit RSA key in PEM format encoded in base64:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnCEy2jOlwK8qVxAHddaD
J6u8u/D0h8nOexco6Xg8iu7DnZOrKPL/1pTL1pwH5GLp0bsb/NfkxetijIb/C4h7
37y6bZPC8V+Koi2jz2lNCNOF4jWuD9Dw8mYnOeH+HpVkKTDVry824i2+qihWM1s/
DwVNUh4C50asnFl64Qd9ycbE3jDr4+yzeBDC7Pirm21OFVUZhTzNzuT5UQzGidvw
2pomYnDM6NOwoIyrBOP0J4CCGbJnZMsf+Dsya/t9tR0cKgFl1Zh0W/V1eJ8Ud7Yq
vIwGeStNeIcjoVkPGh4Hu1Uj0YHXZeTyy4LYo8OUWIipQEJ/dL4TLd0/uD8cr1LR
TwIDAQAB
-----END PUBLIC KEY-----
But the key exported with GPG looks quite different:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
mQENBFSIwoUBCACpyzbyoFLtg8uPMOVl0a4oRdfSSyyNpVuZiDENvj60JINSLhQq
gkyfRW6KbSxp9rEPjsUWnjEVcZ8EYcTZjalGajaG090WrAM0iop4zagKSK3EjpTO
sdkA0wtX7abeK+s9WBiC4hbFk2Ds6iRHtVCU5zsYzZ2S/lD7+PA6UXjFYSpNpCGr
XjyATh7tiYelFjij7ocgK9MWCCDPv6ti9yRVqmsBJPqIqIfvjyyLxFncSOCAc4+E
2cLFUsDr5rGYZF8OsJ0AICxAWwJn50IXpEpuQVQNAOd5yZsrRj4tOJ6qCo/bL24a
UkzF9+zDkFQ6kPSKqUnpOx7wdby5625eBImTABEBAAG0ImdudXBnX2tleXMgPGdu
dXBna2V5c0B5b3BtYWlsLmNvbT6JATkEEwECACMFAlSIwoUCGwMHCwkIBwMCAQYV
CAIJCgsEFgIDAQIeAQIXgAAKCRD3/5Jn+Ps9o7JfCACfQqOVorlkcpya/N9uT/L0
2RA3Y2CwlMEdCpzxUtlEC9KlcAWEMBYfS68Cvq550VKKA+bz9v1XBta1rGPN5T/4
o8lxa7fEhQYCRcUJ4qBzHHOPJoLd7oYDNjGcMS0LNmt7L8Apm2+WguwufO1x61OA
bfOsxCzPt7kl/PjzQMLeNY3F03SuzgtkSQwDc0CpBgoRYhlbCyorxEuTIdRioZiL
h6G/Wvp4Me9prQiMpEqPkHHhp61+LKdAGKjaCcyOwDUB3Ec1GtY1CRKb3/VRveXQ
nN8hm9+VnbqVBy6HurMsz5rEM9rKbIWl1i2A3CFY4EKbJBcYdiGTB16p/QJ+Ll0o
uQENBFSIwoUBCACfH0Up/2Zf+WwH70Tk4WVmaEMNhEiiN1ivYsPT1RYSgSzsgRzx
LgD9CTWCFl9jf6Ko2YCHujZimTpx4Bd2hGNj07zF8VWl2fpW8nA964HkWg1isk5s
XYiSYRSG6foH6tn8D42fYsJad0A4yZo1P5OoPzql9MTJpH1nVjaWnxTOTRgoYmMo
mPW7DimIDnoKRp/A7yCdw3HiUogKqRedqWTxLzs2odhx1NKDx9A3lA81UQtNSA78
o6h1JGPQUHUU5yl3+EgntDL+qmcx4fW2J/PQ2ingIq+VueeDpUKYNomGcrvR7vvR
EAIUCD9UbQTos3xgzUAa6TZY+sLC/x6lTpq9ABEBAAGJAR8EGAECAAkFAlSIwoUC
GwwACgkQ9/+SZ/j7PaPd0gf/TNqUmBgQQaY+kgfUL2rCauNkBZboku59pNxJu6iJ
W+IEMYLbRg8qzIVS1ui9zxMY8pper88QX82jfZ27Xo5nbct9ZZCjDeWZRX5xJULx
CsK2fHlMA/CdvGZJdm5KMNmVFni+vVJlLzpij5eQ52j+8NvHAPFgL3NlcmdwWVhy
/y3XjG687bB+DnVhlfOb7JijA/WHThjXS6AFH659jlt/Z1FRti6O3cxEJSTN0rQU
bCXkjJPsqQNgEbsBDQ3f6hwZKnpqpQZt417qRahb/LrfIgxAJhiWLyFFWKp3XuX3
mR0t01lrPzIXTQMaY9lce3G3XSoQx+1gu29fBm/rkHvQIQ==
=R8UZ
-----END PGP PUBLIC KEY BLOCK-----
Although it's a 2048 bit key as well. If I trim the blank lines and the header, CryptStringToBinary succeeds and translates it into a binary format, but CryptDecodeObjectEx fails (GetLastError() returns 0x8009310B). Removing the checksum didn't work either.
I'm a bit lost here so, basically, Is there a way to obtain a RSA public key exported with GPG and use it to encrypt data with Windows CryptoApi?
Thank you.
Converting OpenPGP Keys to PEM
Extracting the RSA public key from an OpenPGP key and conterting it to PEM format is possible. Sysmisc has an article about converting to and from OpenPGP keys in different ways. For the way OpenPGP to PEM, it boils down to:
gpgsm -o secret-gpg-key.p12 --export-secret-key-p12 0xXXXXXXXX
openssl pkcs12 -in secret-gpg-key.p12 -nokeys -out gpg-certs.pem
OpenPGP has its own Message Exchange Format
Yet a caveat, if you want to encrypt to an OpenPGP user, he will not be able to read any (Open, ...)SSL encrypted information using an OpenPGP implementation like GnuPG. OpenPGP not only uses a different key format, but also another message exchange format.
If you want to send OpenPGP messages, use GPGME to interface GnuPG from C, there might also be other libraries for doing so.

What are highest performance SQLite encryption codecs in Botan?

When using Botan encryption with botansqlite3, what are the optimal configuration settings for performance?
OR
How can I configure Botansqlite3 to use CAST5?
I am currently using AES and it is too slow. My use case is a game.
I am looking for weak or moderate encryption to protect my game's data (not end user data) so security is less of a consideration than performance.
Here is my current BotanSqlite3 codec.h
/*These constants can be used to tweak the codec behavior as follows */
//BLOCK_CIPHER_STR: Cipher and mode used for encrypting the database
//make sure to add "/NoPadding" for modes that use padding schemes
const string BLOCK_CIPHER_STR = "Twofish/XTS";
//PBKDF_STR: Key derivation function used to derive both the encryption
//and IV derivation keys from the given database passphrase
const string PBKDF_STR = "PBKDF2(SHA-160)";
//SALT_STR: Hard coded salt used to derive the key from the passphrase.
const string SALT_STR = "&g#nB'9]";
//SALT_SIZE: Size of the salt in bytes (as given in SALT_STR)
const int SALT_SIZE = 64/8; //64 bit, 8 byte salt
//MAC_STR: CMAC used to derive the IV that is used for db page
//encryption
const string MAC_STR = "CMAC(Twofish)";
//PBKDF_ITERATIONS: Number of hash iterations used in the key derivation
//process.
const int PBKDF_ITERATIONS = 10000;
//KEY_SIZE: Size of the encryption key. Note that XTS splits the key
//between two ciphers, so if you're using XTS, double the intended key
//size. (ie, "AES-128/XTS" should have a 256 bit KEY_SIZE)
const int KEY_SIZE = 512/8; //512 bit, 64 byte key. (256 bit XTS key)
//IV_DERIVATION_KEY_SIZE: Size of the key used with the CMAC (MAC_STR)
//above.
const int IV_DERIVATION_KEY_SIZE = 256/8; //256 bit, 32 byte key
//This is definited in sqlite.h and very unlikely to change
#define SQLITE_MAX_PAGE_SIZE 32768
I believe that I need to find replacements for BLOCK_CIPHER_STR, PBKDF_STR, MAC_STR, KEY_SIZE and IV_DERIVATION_KEY_SIZE to reconfigure BotanSqlite3 to use a different codec.
I found a extensive comparison test of Botan codec performance here:
http://panthema.net/2008/0714-cryptography-speedtest-comparison/crypto-speedtest-0.1/results/cpu-sidebyside-comparison-3x2.pdf#page=5
However, the testing was done with Botan directly, not botansqlite3 as I intend to use it. Looking at the charts, a good candidate appears to be CAST5 from a performance perspective.
The database in question is 300KB, mostly INTEGER fields with some text blobs.
I am configuring Botan as suggested by OlivierJG of botansqlite3 fame, using the amalgamation
'./configure.py --no-autoload --enable-modules=twofish,xts,pbkdf2,cmac,sha1 --gen-amalgamation --cc=msvc --os=win32 --cpu=x86 --disable-shared --disable-asm'
References:
http://github.com/OlivierJG/botansqlite3 - botansqlite3 is an encryption codec for SQLite3 that can use any algorithms in Botan for encryption
http://www.sqlite.org - sqlite3 is a cross-platform SQL database
http://botan.randombit.net/ - botan is a C++ encryption library with support for a number of codecs
You can get CAST-128 (or as I was calling it, CAST5) to work, it is a block cipher.
The best bet is the above with different configuration of key size.
Twofish is pretty fast.
Thank you to 'Olivier JG' for all the excellent code.

RSA encrypt for C++ (BB10)

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

Java and C++ Cryptography interoperability

I have a message coming from an external company which has been encrypted with our public key using Java.
Specifically the java code performing the encryption is -
//get instance of cipher using BouncyCastle cryptography provider
Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding", "BC");
//initialize the cipher with the public key pulled from the X509 certificate
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
I need to be able to decrypt this message using our private key using C/C++ on Solaris.
I have tried using the Crypto++ library and can successfully encode decode messages just using Crypto++, but am unable to work out how to decode the message encrypted from the java side.
Specifically I tried using a RSAES_PKCS1v15_Decryptor but this does not seem to work.
Does anyone have any suggestions as to how I can perform the decryption such as
The required Crypto++ code (ideal)
Alternatives to RSA/ECB/PKCS1Padding to use from the Java side
Alternative open source C libraries I could try
Anything else...
I managed to get this working by changing the java code to use
Cipher cipher = Cipher.getInstance( "RSA/NONE/PKCS1Padding", "BC");
This then matches up with RSAES_PKCS1v15_Decryptor on the Crypto++ side.