I need to decrypt messages via RSA in order to send it over an unsecured channel, but I'm afraid of the Padding Oracle Attack. Therefore I already have asked the follwoing questions:
How to verify the integrity of RSA encrypted messages?
How to ensure message integrity for RSA ciphers by using javax.crypto.Cipher
Like suggested in the first question,
However, since you are using a high level cryptographic library, this is something you shouldn't have to worry about. The writers of that library should have taken care of it.
I shouldn't consider about. As far I know, the RSA implementation of PKCS#1 v1.5 is vulnerable to the Padding Oracale Attack whereby OAEP isn't (assumed it's implemented correctly)
Hence I want to know which padding implementation is used by javax.crypt.Cipher by Java 7
It depends on the chosen or default provider which padding is actually used when you instantiate a Cipher without fully qualifying it like:
Cipher.getInstance("RSA")
Doing so is a bad practice, because if you switch Java implementations, there might be different defaults and suddenly, you won't be compatible with the old ciphertexts anymore. Always fully qualify the cipher.
As I said before, the default will probably (there are many providers, one can't be sure) be PKCS#1 v1.5 padding. If you need another, you would have to specify it. If you want to use OAEP, here is a fully qualified cipher string from here:
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
That's not a good advice given in the first link to the cryptography site. You should never rely on the defaults of cryptographic libraries cryptographic algorithms. There are quite a few reasons for this:
Different implementations, different defaults (there are no requirements for cryptography providers concerning defaults, although most will copy the Oracle/Sun defaults);
What's secure now may not be considered secure tomorrow, and because for backwards compatibility, you can never change the default;
It's unclear to anybody reading your software what the default is (you could document it, but in that case you might as well write it out).
The SunJCEProvider provided by Oracle defaults to PKCS#1 padding ("PKCS1Padding") for historical reasons (see reason #2 above). This is not well documented.
At that time that default was set you basically had just the insecure textbook RSA ("NoPadding") and the PKCS#1 v1.5 version ("PKCS1Padding" or RSAES-PKCS1-v1_5 in the PKCS#1 v2.1 standard). At that time RSAES-PKCS1-v1_5 was definitely the more secure choice. Changing the default now to OAEP would break every RSA implementation out there that uses the default.
The advice of otus (in the first link within this answer) is be better suited to protocol implementations in libraries than to cryptographic algorithms. In the end you should be able to defend the security of the choices made, whatever you choose.
The default for bouncy-castle when you just specify RSA is RSA/NONE/NOPADDING
This is the same result as RSA/ECB/NOPADDING as well.
Related
I am developing a digital signature java class using the SHA1withRSA algorithm with a 256 bits certificate. But I am getting this error:
Signature length not correct: got 344 but was expecting 256.
I am using the SunJSSE provider (that not implements the SHA256withRSA algorithm) because he uses the PKCS12 keystore type. And I need this, because this is a batch application.
Is the SAH1withRSA algorithm incompatible with 256 bits certificate?
First, you can't possibly have a 256-bit RSA certificate, or key. 256-bit RSA wasn't secure when RSA was published in 1977 much less anytime close to now. That exception says it is looking for a 256 byte signature, which is 2048 bits, implying a key and certificate also of 2048 bits, which is currently (since 2015) the standard and widely used size for RSA.
Second, yes SHA1withRSA technically works with a 2048-bit RSA key (and certificate), although it is less secure. SHA1 was originally rated for only 80-bit strength against collision, and has been broken (at significantly lower cost, about 63 bits) about a year ago -- see https://shattered.io -- making it insecure for signatures in many cases, and thus leading more and more systems, programs, and users to reject SHA1 signatures. For example, all Oracle Java packages from 8u144 up (roughly last summer) have java.security jdk.certpath.disabledAlgorithms configured by default to prohibit use of SHA1-signed certificates in TLS (including SSL, but SSL is also broken and prohibited by default). Java doesn't currently prohibit other uses of SHA1 signatures, but may be changed to. And lots and lots of things you might want to communicate or interoperate with, like browsers, webservers, email systems, repositories, etc, either have already prohibited SHA1 or probably will.
But it isn't necessary. You can use multiple providers in one program, and in particular you can use the KeyStore PKCS12 from SunJSSE while also using the Signature SHA256withRSA (or other SHA2+RSA variants) from SunRsaSign. In fact it's easiest to not specify the provider(s) at all and just let KeyStore.getInstance() and Signature.getInstance() (and the other JCA interface classes) find the correct provider automatically.
Finally, your signature is probably base64-encoded: ceil(256/3)*4=344. Take a look at the data and see if it consists of base64 characters, and if so which set. If it is base64, decode it to binary (i.e. byte[] in Java) and use that. In Java8+ just use java.util.Base64 which supports both variants now common: the 'MIME' variant and the 'URL-safe' (primarily JSON) variant. In older Java you can use javax.xml.bind.DatatypeConverter for MIME, or any number of third-party libraries with varying capabilities.
I'm creating a web service that stores a list of users with their public keys online, as well as encrypted messages. My end goal was end-to-end encryption.
I initially thought this would be pretty easy -- "Oh, OpenSSL and RSA private/public key asymmetric encryption is great." False. RSA will only encrypt a tiny bit of data, presumably to pass a regular, symmetric key back and forth.
Okay, so I tried to find solutions online. Most of them either ended without a functioning example or pointed at using the command line, all of which seemed excessive and incomplete.
Is there a way to use end-to-end encryption on data with asymmetric keys, or is it all a personal pipe dream? OpenSSL in PHP has a way to do this already, and it's kludgy but it works.
Is there some method I'm missing here?
The common way to encrypt larger amount of data with a asymmetric keys (eg. RSA) is by use of hybrid encryption. In hybrid encryption you mix symmetric and asymmetric encryption. First you generated a random symmetric key, that is used to encrypt the data. Then you encrypt the symmetric key with the asymmetric key. The encrypted data + the encrypted random key are then put together and makes up the full encrypted data.
The openssl_seal() in PHP you refer to, uses hybrid encryption where the symmetric algorithm is RC4. How data is encoded and put together in the encrypted files have been defined by the openssl implementation, and might not necessarily be the way you would want to do it. PGP, as an other example of hybrid encryption, uses it's own way of packing the data.
In any case, hybrid encryption is not something you get out of the box in java, and you typically need to implement each of the encryption + packaging steps yourself, or use one of the libraries that implements there version of this. An example of doing it yourself is this Java code I found that can decrypt messages encrypted with the above mentioned openssl_seal().
An example of using a library for hybrid encryption, could be using the PGP support in Bouncy Castle.
Ebbe's answer is very good, however this question was highly ranked in Google in my attempt to try and find a decent hybrid encryption library (Bouncy Castle's documentation is non-existent and not straight-forward, and GnuPG for Java relies on the OS and is not fully tested). So I thought I'd add on to Ebbe's answer for the weary traveller.
If you can use them, JWTs (JavaScript Web Tokens) could be handy for this. It's also an IETF Standard. There are two different types:
JWS, which is a signed JWT. Plain-text message, but you can verify its authenticity. Which has its own IETF Standard
JWE, which is an encrypted JWT. Which also has its own IETF Standard
Support for JWEs are unfortunately a bit poor at this point in time. However this should hopefully improve. At this point in time (2017-04-11), the only Java JWT library that supports JWEs is BitBucket's Jose4j.
I'm not really sure what you're trying to en- and decrypt, but GnuPG for Java might be a good choice.
It supports public and private keys and can en- and decrypt bigger files and data.
I have just watched a crypto 101 talk which said if you are typing the letters "AES" into your code, you're doing it wrong! The solution was to "just use GPG".
If you are storing your data on the cloud, all readers and writers need to know the key. If the key is a public private key, that's just a slow key but not a more secure key than just having a good password?
What standard alternatives are there to GPG that properly encrypt data at rest but use a shared secret instead of public keys?
I use Java, and would like to use a library, but want interchange with other platforms.
The solution is wrong in terms - you don't use "GPG" but OpenPGP.
Indeed for encryption using shared secrets (passphrases and alike) OpenPGP is optimal, as it supports multiple methods at the same time and includes compression.
The alternative would be to use CMS encryption with keypairs derived (in some predetermined way) from the shared secret. However such scheme is not standard.
I can remember also XML encryption that supports encryption with symmetric keys, but it has certain security flaws.
So OpenPGP is probably the best way to go.
Regarding compatibility - OpenPGP-compliant library should create packets that can be later processed by any other OpenPGP-compliant library or application. Unfortunately OpenPGP implementation in popular BouncyCastle library sometimes produces not compliant packets - we came across its issues several times when packets created with BouncyCastle could not be processed by GnuPG or our SecureBlackbox due to issues in the packet created.
I am using password based encryption. My initial thought was to use AES to encrypt the file which contains passwords. Turns out password based encryption does not support AES. It uses DES. AFAIK des is not secure. Is PBEWithMD5AndDES secure enough to thrust my data or should i look for another implementation?
It appears from your comments that what you would like to do is to encrypt a file which contains sensitive information, using a password-based encryption scheme, with a password provided by the user at decrypt-time. The sensitive information in this case also happens to be passwords, but that isn't really relevant. (You should probably update the question to make this more clear).
You are doing the right thing, your problem is just that the SunJCE Java cryptography provider doesn't support AES for password-based encryption. You need to use an alternative provider which does: for example, you could use the Bouncy Castle provider with the algorithm "PBEWITHSHA256AND128BITAES-CBC-BC". (Despite the whimsical name, Bouncy Castle is well-respected).
As for "is DES secure enough for my data", well if the data you're protecting would be worth less than roughly $10,000 to an attacker, then back in 2009 it was probably just secure enough. And in 2014, if your data is worth encrypting at all, the answer is no.
If you have Java 6 available, everything you need is available. Check out this question and look at the accepted answer for a code sample. Since you want to encrypt files, the iv that is generated should be prepended to the file you are writing the ciphertext to, so that it is available during the decryption.
You should not be keeping the passwords in any form other than salted hash digests.
You should then use the operating system permission system to make it such that the hashed password file is only readable by the user which validates passwords.
I've been working on a system that uses asymmetric encryption in a large number of files. I'm currently using RSA with 4096-bit keys to encrypt a 256-bit randomly generated AES key for each file, but performance is somewhat lacking, as one required operation is to scan through all the files (estimated number when the system is in use is around 10,000) and identify which ones can be decrypted using a specific private key. While I don't expect this operation to be instant, it is taking too long at the moment (~2 files processed per second). I considered reducing the key length, but even taking it down to 2048 bits doesn't provide the level of performance I need. 512 bits would just about cut it, but as such keys can now be cracked trivially that is out of the question.
Can anybody point me in the direction of a system that is faster but of similar cryptographic strength? It would need to be implemented via a Java JCA provider (e.g. something like bouncycastle) in order to plug in to my existing application neatly. I know bouncy castle supports El Gamal, but I can't find any details on how strong this algorithm is, or if it is even likely to be any faster than RSA. I also hear about elliptic curve systems that only need relatively short keys (384 bits or the like), but don't know where to find an implementation of one of these.
For your question as asked, try Diffie-Hellman over elliptic curves, also known as "ECDH". Estimating security is a bit difficult once we deal with sizes that cannot be cracked with current technology, since this depends on how we bet on future technological evolutions. Yet one can say that ECDH over the P-256 curve provides "128 bits" of security, a level which is similar to what you would get from 2048-bit RSA. That level is widely sufficient for all current usages, or, more appropriately said, if P-256 is not enough for you then your problem has very special needs and cryptographic strength is likely to be the least of your worries.
On my PC (a 2.4 Ghz Intel Core2, 64-bit mode, running Linux), OpenSSL claims to crunch out about 900 ECDH instances per second, using a single core.
Edit: for estimation of key security, depending on the length, for several algorithms, see this site.
Why don't you calculate a cryptographically strong hash of each key, and then store that in the clear with each filename? Then, given a key that you need to match against all the files, you can simply hash the key and look it up in the table.
I'd go for an approach that requires less RSA operations. SSL/TLS, although they use RSA etc for encrypting AES etc keys, do not use AES for the data simply because it is a computationally expensive operation at sufficiently large key sizes for security to be done on a per-packet, or in your case, per-file basis.
Another public key system is: http://en.wikipedia.org/wiki/ElGamal_encryption. Security-wise I believe it has yet to be broken but would personally put my trust in RSA for now. I do not know if there are any elliptic curve encryption algorithms currently available - that is to say I know they are being researched but understand they may not be ready for production use and I heard there were patent issues.