I am writing software in Java that will run on Android, Windows, Linux and OSX and want the devices to all talk to each other securely.
My initial thought was just to use a asymmetric algorithm (eg. RSA) and share the public keys manually. Then sessions would be encrypted just using RSA. I hit problems with this due to buffer size, then I read about CBC etc and the problems of data leakage if some form of XOR of data was not performed.
So...I looked at using AES/CBC/{padding}. Initially this sounded good: just share the key, an IV and away we go.
But these apps all talk to each other in both directions at any time, so keeping the IV in sync did not seem possible, resulting in a new IV being sent with every message. Not a big deal, but one of the advantages of AES over RSA is data size, and now I'm going to be adding 32 bytes to every message. Though I guess keeping a 'receiver' and a 'sender' Cipher would probably work.
Now I am back to considering alternatives, and trying to avoid too much roll-your-own.
Is there any substantial reason not to use RSA and CBC (or similar) done manually? ie. break data into chunks, pad as necessary, and encrypt with RSA, doing whatever XOR strategy seems most reliable.
Is there a better was to keep secure and trusted comms between pairs of peers without creating an SSL CA? Or, is there a way of hooking into the certificate verifier so that I can use my pre-shared public keys to validate the peer connections?
Any other suggestions/examples for best/simple multi-platform peer-peer secure comms?
You should look into implementing a hybrid cryptosystem. If I can guess your knowledge about the subject correctly you should really be using a pre-existing one like TLS, or DTLS, as you're not going to design a cryptographically safe protocol out of the blue.
Note that the certificates are required to create a PKI, and the asymmetric crypto of course comes with it. You should however only have to use the asymmetric crypto during the handshake which includes the initial authentication and session key negotiation.
I want to add cryptography to my program and after some research on cypher algorithms i found about AES and AESWrap and my main question is, how are they related? To be honest i don't realy understand the whole process since i've never used crryptography before. At first i thought that AESWrap was the AES's decription key but it's something more than that.
I am developing a chat program in java and i want to encrypt the streams of String, so basically any outside attacker unless he knows the algorithm's process and the keys from server and client he can't get access to the stream. I thought of using Blowfish but from papers i read it appears that even though it's fast it has some problems in its rounds. Now i am digressing so to sum it all up, do i "have to" use AESWrap with AES or are those two completely different?
AESWrap is an algorithm describing a way to encrypt encryption keys. You don't need to use AESWrap to use AES. You might use AESWrap if you need to encrypt the encryption key.
If you are developing a chat program, why not use SSL/TLS to secure the communication? Using symmetric key algorithms (alone) like AES gives the problem of distributing the keys to both ends. A problem SSL/TLS solves by use of certificates.
I am writing a secure file sharing application in Java. The general architecture looks like this:
User wishes to encrypt a file for secure sharing between multiple users.
The application generates a random UUID on the client and uses this as the AES 256 password, and encrypts the data with the UUID.
The UUID is then RSA encrypted with each person's public key. Once per shared user.
Each encrypted UUID packet is stored as part of the file in a custom file header.
The file is then uploaded to a server where others can access it.
The user's can each use their private key to read the AES encryption key and decrypt the file.
Here is the catch. The user's private key must be encrypted and stored on our servers in our database so that the files can be accessed from multiple locations. The private key will be encrypted with a user selected password on the client prior to being uploaded to the server.
I would like to do this using AES 256 bit encryption. And I would like to do the entire thing without relying on BouncyCastle libraries or any 3rd party libraries. It needs to use the standard Java 5 libraries, which is why I have chosen to use AES 256 encryption and RSA rather than something like PGP.
Can anyone find anything inherently insecure with this approach, or think of a more efficient way to do this?
Edit:
OK, I'm updating the question because all of the answers I am getting are suggesting that I not transmit the private key to the server. The reason I need the private key on the server is because the user's need to be able to access their data from multiple clients and multiple locations (ie: their iphone, their ipad, their work laptop, their home pc). They do not want to have to manage and copy their keys from device to device, which is even more insecure than storing their keys on our server because they would just end up emailing them to themselves at that point.
The big problem with this is using UUIDs. Although UUIDs are (sort of) guaranteed to be unique, quite a bit of what they contain is quite predictable; substantial amounts remain constant across all the UUIDs generated on a single machine. As such, if a person gets access to (for example) their own key, they can probably guess many other people's keys fairly easily.
The other part that's problematic is storing user's private keys on the server. This makes the whole rest of the scheme relatively fragile, since access to those keys obviously gives access to all the rest of the data. It also (apparently) means you'll normally be decrypting the data on the server, so when the user accesses that data across the network, it'll either need to be re-encrypted for transmission, and decrypted on the users's machine, or else you'll be transmitting the data in the clear (thus rendering most of the encryption useless).
Edit: As to how I think I'd do this:
I'd have a list of public keys on the server. When a client wants to share a file with some other clients, it obtains the public keys for those clients from the server. It then generates a secure random key, and encrypts the data with that key. It then encrypts the random key with the public keys of all the other clients that are supposed to be able to access the data. Put those together into a stream, and transmit them to the server. The other clients can then download the stream, decrypt the key with their private key, and use that to decrypt the data itself.
This means each client's private key remains truly private -- it never has to leave their machine in any form. All they ever have to share with the rest of the world is their public key (which, by definition, shouldn't cause a security problem).
With that, the two obvious lines of attack are against the random number generator, and against RSA itself. For the random number generator, I'd use Java's SecureRandom -- this is exactly the sort of purpose for which it's intended, and if memory serves it's been pretty carefully examined and significant breaks against it seem fairly unlikely.
I won't try to comment on the security of RSA itself. For now, I think your primary concern is with the protocol, not the encryption algorithm proper. Suffice to say that if RSA were significantly broken, you'd obviously need to change your code, but you'd have a lot of company.
With this, it's pretty much up to the client to store their private keys securely. I like smart cards for that job, but there are quite a few alternatives. From the viewpoint of the server and protocol, it's no longer really a factor at all though.
Edit 2: As for dealing with multiple devices, I think I'd simply treat each device as a separate user, with its own public/private key pair. I'd then (probably) group those together by the actual users, so I can easily choose "Joe Blow" to give him access on all his devices -- but with a hierarchical display, I could also pretty easily restrict access to a subset of those, so if I want to share it with Joe on his office machine, but it's sensitive enough that I don't want it going where somebody might look over his shoulder while he looks at it, I can pretty easily do that too.
This keeps life simple for the users, but retains the same basic security model (i.e., private keys remain private).
The scheme you outline is equivalent to CMS (the standard underlying S/MIME) and PGP; fundamentally, it is secure. In CMS, this mode is called "key transport". You could also use multi-party "key agreement," with an algorithm like DH or ECDH.
The only problem is that you are using poorly chosen keys for AES.
I can't think of any reason to use a random UUID, which contains non-random bits. Just use the normal key generation mechanism of the Java Cryptography Architecture. Keys, plaintext, and ciphertext should all be represented as byte sequences, unless you need to accommodate some external storage or transport that only accommodates text.
Iterable<Certificate> recipients = null;
KeyGenerator gen = KeyGenerator.getInstance("AES");
gen.init(256);
SecretKey contentEncryptionKey = gen.generateKey();
Initialize the AES cipher and let the provider choose an IV.
Cipher contentCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
contentCipher.init(Cipher.ENCRYPT_MODE, contentEncryptionKey);
AlgorithmParameters params = contentCipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
For each recipient, initialize the RSA cipher and encrypt the AES key.
Cipher keyEncryptionCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
for (Certificate recipient : recipients) {
keyEncryptionCipher.init(Cipher.WRAP_MODE, recipient);
byte[] encryptedKey = keyEncryptionCipher.wrap(contentEncryptionKey);
/* Store the encryptedKey with an identifier for the recipient... */
}
/* Store the IV... */
/* Encrypt the file... */
Having users select and remember passwords that give 256 bits of effective strength is unreasonable. To get that strength, you'd have to randomly choose passwords, encode them as text, and have users write them down on a card. If you really need that much strength, you could check out a smart-card–based solution for storing the users' RSA keys.
I'd highly recommend using a CMS library to store your files. It will increase your chances that the protocol you're using is safe, the code you are using has had more review, and that other tools, libraries, and systems can inter-operate with the encrypted messages. BouncyCastle's API is a little obscure, but it might be worth learning it.
(I can't remember if Java 5 supports "RSA/ECB/OAEPWithSHA-512AndMGF1Padding"; if it does, you should use that instead of PKCS1Padding.)
OK, this question is asking for a protocol discussion, so it is not completely according to stackoverflow's standards. That said, let's see if we can make some remarks anyway :) :
The Bouncy Castle PGP libraries have a very permissive license, so you can even copy them into a sub-package within your code;
Besides PGP there are also other standard container formats such as CMS or XML encryption, although the latter might not be such a good general purpose format;
Instead of UUID's, I would strongly suggest to use a well seeded PRNG such as the Java JCE "SHA1PRNG" to create the AES keys - I don't see any strong reason why you should rely on something like an UUID in your scheme;
AES keys are supposed to consist of random bits to have enough entropy, thinking of them as "passwords" is leading into a trap: you cannot use a String as a secure AES key;
The user will have to trust your application and server, you are acting as a trusted third party: you can send user's passwords to your server, you can send incorrect public keys to the users etc. etc. etc.
Your scheme is not protected against any man in the middle attacks (and many argue this cannot be done without using SSL)
Instead of directly encrypting with a password, you should look into something like Password Based Encryption PBKDF2 to encrypt the RSA private key;
Try and add integrity protection when encrypting, from Java 7 onwards you may use AES in GCM mode, it's well worth it.
It all depends on how "secure" you want the encryption to be. Obviously RSA is a well document/accepted standard for PKI. That being said, any time you provide the plaintext as well as the encrypted text, it makes it significantly easier for a hacker to decrypt the ciphertext knowing part of the plaintext. Here, you are doing precisely that. Although you are only transmitting the encrypted UUID, by having the same plaintext encrypted with multiple keys gives an attacker significant insight into the payload. Furthermore, if the hacked is actually one of the recipients, he is able to decode the UUID, and thereby automatically knows the plaintext that is being encrypted by the other users' public keys.
This is not likely a critical issue for you, but just thought I would point out a security risk.
I am not entirely sure why you need to store the user's private key, however. Furthermore, by using a simple password to encrypt the private key, you have basically reduced the overall security of the entire system to the strength of the user's password. Finally, if the user loses his password, he is toast; no way to recover any data.
I did something similar in the past but stored the results in a DB. However, I used the BouncyCastle libraries at the time, so am not sure how to accomplish this without them.
I want to know if our data is encrypted with one encryption algorithm(AES, DES, etc.) and then we transfer our data in open network, can anyone get real data or do some thing if the encryption algorithm is known even though the hacker doesn't know about the private keys, public key or PV?
can anyone get real data or do some thing if the encryption algorithm is known
If the attacker knows the encryption algorithm, it's a start, because now all they need to do is to find out what was the key used to encrypt it. But established encryption algorithms like AES have no known weaknesses. Thus an attacker would be forced to bruteforce it to gain access to the data.
If you are using keys of an appropriate size (eg: AES 256 bits or more), this would be a very difficult task. DES also has no known weaknesses, but its small key size (56 bits) allows for a bruteforce attack to succeed in a reasonable timeframe, (eg: days). That's why DES is not widely used any more.
even though the hacker doesn't know about the private keys, public key or PV?
Note that public keys are only relevant in the context of asymmetrical encryption. In this case, the public key is usually publicly available (hence, the name "public key"). But asymmetric encryption is designed so that even if you know the public key, you can't decrypt it unless you have the private key.
In summary, encryption algorithms like AES have stood the test a time and proven to be secure enough. As David Schwartz points out in his answer, if you have a problem, (usually) your implementation is the thing to blame, not the encryption algorithm.
Almost by definition, if the encryption is implemented properly and part of a sensibly-designed system, no. That's the whole point of encryption.
Note that encryption is not magic. It must be used precisely correctly to provide useful security. There are a lot of ways to do it wrong.
If you're not using a widely respect product (like TrueCrypt, Firefox, or GPG) and using it precisely how it's intended to be used, there's a very good chance you aren't getting real security. For example, Dropbox used AES, but a security flaw in another part of their system allowed one user to decrypt another user's data. So it didn't help that it was encrypted.
Yes, keeping the algorithm secret helps security marginally. If an attacker knows that you used DES (which isn't terrifically hard to break) they may be more likely to try to break it.
I think the core of your question is about statistical attacks, which tries to see through the encryption to decipher the nature of the data. Any reasonably modern algorithm is mathematically designed to thwart any attempts to guess what the data is.
However David makes a very good point. Even perfect encryption (if it existed) would be vulnerable to the human factor. These algorithms are worthless if you don't dot your i's and cross your t's, and have absolute (and justified) faith in those who can decrypt the data.
I am programming some server-client software and wanted some encryption. Both the server and client share a private key which is fixed length. Haven't decided what length I am going to have the key, but I do know that the key will be between 1 and 32 characters. The key is predetermined (so for instance I may decide I want the key to be abc1234)
I am programming in Java and need the algorithm to be a quick as possible as the clients are most likely to be mobile devices. I don't need any compression but I would prefer if the encrypted string wasn't larger.
I am not looking for top-notch encryption here obviously, but it is my understanding that any key based encryption can't be broken without knowledge of the private key anyway.
Can anyone recommend me an algorithm/method for encryption/decryption with a shared private key?
it is my understanding that any key based encryption can't be broken without knowledge of the private key anyway
That's not even close to true. A lousy algorithm absolutely can be broken without knowledge of the private key.
Anyhow, if there's a shared key, consider AES.
And read up on the JCE/JCA as Java can do AES and other types of encryption out of the box. Much better than rolling your own.