2

I am building an application that requires secure data transfer. In particular, the sender has a data file that needs to be sent to the receiver. It is required that only the receiver be able to read the data. It is also required that the receiver can know for sure that the data comes from the sender.

The sender and receiver have a long-term business relationship, and will have exchanged public keys. The data files to be transmitted are not small.

I am assuming that Bouncy Castle is a good route to go, but I am open to other suggestions.

I have read all the BC documentation I can find (none) and look at the API and some examples I found on the internet. It appears that I want to be using CMSEnvelopedDataGenerator, but I have some specific questions:

  1. Exactly how do I configure the data encryption (presumably using AES)?
  2. Exactly how do I configure the double-signing (using sender's private key and receiver's public key)?
  3. Can I configure it so that the data is zipped/compressed before being encrypted?
  4. Is the BC implementation of this scenario secure and safe to use? Are there specific settings/algorithms/parameters that are required to make it secure?
  5. Is there an available 3rd-party, standalone application that I can use to read/validate that the BC output is indeed correct and secure?
  6. What else should I be asking (I am a crypto newbie)? Or is there a better way to do what I am looking for?

Follow-up question In doing further research, I ran across this article. My requirements are such that I need to not be susceptible to surreptitious forwarding. The article is old. Do the various "secure" technologies still suffer from the mentioned faults? Do any of the standard products/libraries provide a secure solution in a standard way?

Rob
  • 121
  • 1
  • 4
  • Should the receiver be able to prove to a third party who the sender was? – CodesInChaos Jun 07 '12 at 23:04
  • @CodeInChaos CodeInChaos - Yes, the receiver needs to be able to prove (to self and others) not only that the file comes from the sender but also that the sender sent it to the receiver (was not surreptitiously forwarded). In this scenario, I am the receiver and I am going to take actions of consequence (e.g., transfer large sums of money) based on the file received. I need to be able to know that I am doing the right thing, and prove it to my boss and an auditor. If something bad happens, I need to be able to point the finger at someone other than me :-) – Rob Jun 08 '12 at 18:35

4 Answers4

2

The BouncyCastle OpenPGP or S/MIME packages should allow you to do what you want. OpenPGP will be more appropriate when using OpenPGP certificates (often only referred to as "PGP public keys"), whereas S/MIME will be more appropriate when using X.509 certificates.

There's no "double-signing" involved: you'll sign with the sender's private key and encrypt with the recipient's public key.

GnuPG (or other implementations of OpenPGP) should allow you to test the results if you use BouncyCastle's OpenPGP implementation.

Note that you should sign first and encrypt afterwards, not the other way around, on the basis that the signer should be able to look at what it signs, and the recipient to be able to decipher and read, but keep the signature attached if necessary.

There doesn't seem to be many BouncyCastle OpenPGP examples around, but this blog entry looks rather complete (although I'd still sign first and encrypt afterwards). Compression is also taken into account.

Bruno
  • 10,765
  • 1
  • 39
  • 59
1

I have no experience with the Bouncy Castle API but I'll try to put things straight crypto-wise and it may help you find your way (since you mention you're a crypto newbie):

Q1: It's a two step process:

  • First you encrypt your message using a symmetric key algorithm like AES.

  • Then you encrypt the key of the previous step using a non-symmetric algorithm (e.g. RSA) and the recipient's public key.

  • You send your (symmetrically encrypted) messages along your (non-symmetrically encrypted) key to your recipient. He uses the same (non-symmetric) algorithm and his private key to decrypt the key that will give him access to the (symmetrically encrypted) message.

Q2: Only the sender signs his message using his own private key. In a nutshell the process is: (1) Make a hash of the message (2) encrypt it using the sender private key (3) send the message+the encrypted hash (4) the receiver makes a hash of the received message (5) he also decrypts the received encrypted hash using the sender's public key (6) if the two match then the message really comes from the sender and it has not been tempered with along the way.

Q3: This has nothing to do with the crypto API; find a library that will compress your messages and use it before you apply cryptography.

Q5: I would expect that if BC implements the crypto standards correctly it would be interoperable with OpenSSL or GPG etc.

Q6: Have you considered using a ready solution like GPG or OpenSSL (e.g. within scripts?) You could also use the signing/encryption functionality of your email clients (using S/MIME) and self signed certificates (e.g. MS Outlook has embedded digital signature/encryption functionality, most other email clients do too.)

George
  • 2,813
  • 2
  • 23
  • 39
  • Georgios, thanks for your answer. I think I was not clear enough about one of the requirements: the sender doesn't want anyone but the recipient to be able to read the message (in addition to the recipient knowing for sure that it is from the sender). Does the usual CMS envelope allow double-signing, or do I need to envelope+sign with one key and then use that as the message within a second envelope signed by the other key? Thanks! – Rob Jun 05 '12 at 16:29
  • 1
    Q1: The scheme proposed here for Q1 doesn't meet the requirements: it does not provide sender authentication, and it does not provide security against chosen-ciphertext attacks. [You need to use a digital signature or MAC](http://security.stackexchange.com/a/2206/971). Q6: good advice! – D.W. Jun 06 '12 at 03:57
1

To answer your questions 1-3:

I am using the BouncyCastle 1.47 API (ie, with the lightweight operator interfaces) with openPGP for the public/private key implementation. It is indeed quite a chore to figure out what's going on; but I had a stab at it recently. Caveat emptor, as all I can say is that "it works for me (TM)".

Please look at the encrypt method to see some code to accomplish this.

I also use the "anonymous recipient" header, which prevents someone who can see the data from identifying the recipient's public-key id (even if they cannot decrypt it.) This may or may not be relevant for you, but with this mechanism, you should also use the appropriate decrypt method which tries all available keys.

I can't speak for questions 4 & 5, but some openPGP specific thoughts for question 6:

1) Debugging your generated content with GnuPGP is a good way to identify problems.

gpg --list-packets is also very helpful.

2) Create a keyring with separate signing and encryption keys (so you'll actually be using 2 sets of public/private key pairs). Some theories on why this is needed.

2) Use explicit, appropriate length keys where possible, as the default java-based provider creates fairly short keys. (See key generation code for some options.)

3) You may want to consider "pre-building" a signed revocation message at the time of key generation, in case one of your parties forgets their password or loses their private key. This can be released to invalidate previously exchanged public keys.

kbs
  • 801
  • 6
  • 7
0

I recommend that you use GPG (GnuPG) or PGP or OpenPGP to encrypt and sign your messages. Their message format and cryptographic code is well-vetted. Using an existing cryptographic format and code is more reliable doing it yourself with BouncyCastle, as it'll save you from details that otherwise you might screw up. That should make solving your problem pretty easy.

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 1
    Thanks for the answer. I am on-board with using a standard implementation. However, I need to access the data in Java app and I cannot allow plain text of the file to ever hit the disk. Do your suggested solutions allow me to satisfy this requirement? How? Also, are the suggested solutions still vulnerable to the exploit described [here](http://static.usenix.org/publications/library/proceedings/usenix01/full_papers/davis/davis_html/index.html)? – Rob Jun 08 '12 at 18:30