RSA version and its security with openssl - security

I am looking for a strong encryption algorithm (already having generated a public key and private key).
I am using OpenSSL to generate RSA with 2048 bit key-length using an implementation in PHP. I just wanted to know how I can securely use the key for transmitting data.
What version should I use for RSA? How can I determine the version of RSA for the key generated by OpenSSL?

RSA encryption can be implemented using different padding mechanisms. To be precise RSAES-OAEP and RSAES-PKCS1-v1_5. These have been initially defined in different versions of PKCS#1, v1.5 and v2.0. I presume you mean this as "RSA version". There is also RSA KEM, which is probably the best mode to use for encryption, but it isn't used that much.
Both padding mechanisms however use the same keys. The only difference in keys is normally a key with or without CRT parameters. CRT parameters are used to speedup RSA private key operations 4-fold, they are generally included. The keys themselves do not specify for which padding mechanism they can be used.
It is however possible that the public key is embedded into a certificate that does specify different key usages. Even those however do not specify the padding mechanism itself.
So basically there is no such thing as an "RSA version" for keys.
If you can choose a padding algorithm, go for OAEP. Note that you should encrypt with the public key of the receiver, not a key from your own key pair. You should however use your private key to sign the encrypted data to make it unfeasible for an attacker to change the data in transit.

Related

Using ursa (nodejs module) to generate a symmetric key?

I'm using ursa (nodejs module) to do the following:
Use a private key and someone else's public key to generate a symmetric key
Encrypt some data with the symmetric key
Encrypt the symmetric key with the user's public key
However, I can't seem to find any methods that allow me to create a symmetric key. My understanding is that simply generating a pseudo-random byte string should be good enough for the key, but then I can't use the rest of the method in ursa to actually encrypt anything because it's a random string and not a key/cert.
Am I missing anything?
URSA as the name suggests is an RSA implementation and as such doesn't not handle symmetric encryption. If you want those, then you can use node.js' native crypto module which provides everything you need in this regard.
Encrypt the symmetric key with the user's public key
This means that the symmetric key is simply data. URSA doesn't have to know what this is.

Reverse Public/Private key Encryption?

Might be an unqualified question, but are there any encryption systems where two encryption keys are generated (one public, one private), and...
A) The public key is used for encrypting the information, but cannot be used to decrypt it
B) The private key is used for decrypting the information, and cannot be used to encrypt it.
I am asking because I see this as the only practical way to secure a login session to a web service (such as a forum) without the use of SSL/HTTPS. Though, with my limited knowledge of system security and cryptography, it's more than likely that I'm wrong.
The most common private key encryption algorithm is RSA. However, if you don't know what you're doing, stick to higher level constructs such as SSL/TLS.

Protecting a file using asymmetric cryptography

I know how asymmetric cryptography works. I know there are two keys (one private and one public).
When someone wants to communicate they exchange their public keys encrypt messages with those public keys AND then the respective message could be decrypted ONLY by the user that has the private key.
Now, I'm using Node.js and I need to do something like this...
I need an application that EACH hour reads a database, extracts data and saves it to a file that I need to send to another server.
My problem is that I DON'T WANT that file will be visible to other, I do the transfer using SSH so there is no problem BUT
I must encrypt that file because I'm not the admin of that server SO maybe someone could read it. Unfortunately the admin is the same for both servers.
So my idea is to encrypt the file with a public key, and then only he who has the private key(me) could decrypt it.
I think it is pointless using something like:
var key = 'blablabla'
If I use a public key, there is no problem, all can read it..... it is public indeed. But with this public key, nobody can decrypt the message, so it is
something like one-way encryption.
Now, could someone tell me if I need a signer/verifier to do this job, OR maybe I have to generate two keys (public/private) with openssl and pass those keys to a cipher/dechiper?
I'm looking at crypto modules, but there are no examples....
In general, your idea is right - you encrypt using public key and decrypt using private key of yours. However, practically the procedure is more complex. Random symmetric key is generated and the data is encrypted using that key. Then the public key is used to encrypt the random key. Encrypted key is sent to recipient together with encrypted data. On the other side encrypted key is decrypted using a private key, then the data is decrypted.
You can use OpenPGP keys or X.509 certificates to do the job.
In case of OpenPGP the standard offers encryption and decryption as atomic procedures (on the user level). In case of X.509 certificates you need to use PKCS#7 / CMS.
OpenSSL library offers operations with PKCS#7 / CMS, however when I look at nodeJS API for OpenSSL, that API is very limited and doesn't expose those functions. Maybe you can write your own nodeJS module which will interface with OpenSSL and provide missing functions.
Another alternative is to use OpenPGP keys and node-gpg module. That module uses gnupg to do the actual job, so gnupg must be installed.
Unfortunately I don't see any other suitable libraries in the 3rd-party module list provided in nodeJS wiki.

Can I use PBKDF2 to generate an AES256 key to encrypt and implicitly authenticate?

I have 2 devices and I want to set up a secure communication channel between them. The only shared secret is a (7- to 20- character ASCII) passphrase. If I use PBKDF2 (from RFC 2898) with a common salt, iterations, and passphrase to generate an AES256-CBC key and IV on both sides, I think I can authenticate the user and provide an encrypted channel all in one step. Is that true, or is there some reason why I've only seen people use PBKDF2 to verify passwords?
My reasoning is that both sides need to know the passphrase to generate the same key and IV. So if device B can decrypt data from device A, they both have demonstrated that they have the same passphrase.
PBKDF2 is a fine way to generate a common key from a shared secret (you should not be generating the IV in such a way though - the IV should be random, and sent alongside the ciphertext).
However, CBC is not an authenticating cipher mode. This is because an attacker can take an encrypted message and make predictable modifications to it, without needing to be able to read the message or know the key. Such attacks have broken real world systems in the past.
You can use an authenticating cipher mode, like Galois Counter Mode (GCM) instead of CBC.
An alternative is Encrypt-Then-MAC. Use PBKDF2 with two different salts to generate two different keys - first the data is encrypted using CBC with the first key, and then a HMAC is calculated over the ciphertext using the second key.
You will also need to use single-use-nonces to prevent replay attacks.
In general, you wouldn't be able to authenticate a message using a cipher, because the message could be anything. However, if the message conforms to some specified format, I suppose it's reasonable to assume the ciphertext must have been produced with the shared key—with longer messages in more complex formats giving better assurance. For example, the padding in a block cipher can serve as a weak authentication.
For better security, compute a MAC using the shared secret and send that with the ciphertext.
While PBKDF2 can be used to produce an IV, it can only do so for a single message. In most cases it's better to select a random IV and send it with the ciphertext.
PBKDF2 does not "verify passwords". It generates keys from passwords.
To verify a password, normally you have a thing that gets encrypted with a key. The key is generated from the original password, via PBKDF2. Then the cryptotext is saved.
When you want to check whether the user-entered text matches the password, generate the key from the password candidate using PBKDF2, then try to decrypt the saved cryptotext. If the decryption works, then you have a match.
Normally, though, you would not use the password-based key as a session key.
So, NO, you normally would not protect the secure channel with the password-based key.
caf's answer is good. I'd just like to add that you're trying to implement crypto, and even for trained experts that's generally a bad idea. Using the highest-level library you can is much safe.

How does the RSA private key passphrase work under the hood?

RSA private keys may be assigned a "passphrase" which - as I understand it - is intended to provide some secondary security in case someone makes off with the private key file.
How is the passphrase layer of security implemented?
ssh-keygen uses OpenSSL to generate RSA keys and store it in PEM format. The encryption you are talking about is specific to PEM. If you look at your key file,
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,5B01E932988DC66B
EPESt4ZVIrxnQXxxWWVa7cCR+vgNZ/4vTu4mdq6pjaW7jMZoB8HV+mA745mQkQw7
i+YtdVs/JqOeyGiw/3McxYYKZTlhyh7MvfIr1n8ZdZmcjQz+oFqMxChFU3r8BGgA
"DEK-Info" header has all the information you need to decrypt the key as long as you know the passphrase. "DES-EDE3-CBC" means Triple DES (in EDE mode). CBC is the chaining mode. The hex number is the initial vector needed for CBC.
PEM is a very old format so it only supports DES/TripleDES. AES and Blowfish were added later on but not supported by all implementations. My ssh (OpenSSH 5.2) only supports DES and TripleDES.
The passphrase is just a key used to encrypt the file that contains the RSA key, using a symmetric cipher (usually DES or 3DES). In order to use the key for public-key encryption, you first need to decrypt its file using the decryption key. ssh does this automatically by asking your for the passphrase.
If somebody got a hold of the key's file, they wouldn't be able to use it unless they knew the passphrase used to encrypt the file.
Private keys stored on general-purpose file systems (as opposed to tamperproof, special-purpose hardware tokens) could be easily stolen if not protected. File system permissions might seem sufficient, but they can often be bypassed, especially if an attacker has physical access to the machine.
A strong symmetric cipher, keyed with a good password, helps prevent this. A good RSA private key is too long to remember (for me, anyway), but far smaller symmetric keys can provide the same level of security. A relatively short, symmetric key stored in one's brain is used to protect a large private key stored on disk.

Resources