1

I have a requirement to secure the Java RMI calls with Asymmetric key cryptography (RSA) in a Peer 2 Peer File sharing application.

I referred this, but it uses a passphrase (Symmetric Key) to XOR the messages. I want that the client encrypts the RMI Socket stream with server's public key and the server should use its private key to decrypt the socket input stream. Assumption: Every node in the P2P File sharing application has each other's public key

Since there can be multiple client-servers (P2P nodes), the clients should use the relevant server's public key to encrypt the socket stream data.

I could not find any other reference using asymmetric key to secure RMI calls. Please help.

UPDATE:

I'm a student and this is a university project where I have to secure the communications happening over the RMI using RSA cryptography. So, I don't have any choice left.

In the previous projects, I created a Napster & Gnutella style P2P file sharing system. Now the task is to use RSA to encrypt the communications between nodes using their public-private keys.

I really appreciate any help/guidance in this direction. Please do not close this question.

UPDATE 2 Implement RSA cryptography without using in-built libraries except java.math.BigInteger and java.security.SecureRandom

Maverick
  • 1,519
  • 18
  • 32
  • 1
    You would have to implement your own `RMIClientSocketFactory` and `RMIServerSocketFactory`, or else use `SealedObject` for every parameter and result. – user207421 Apr 22 '20 at 04:23
  • How do I update the Client Socket Factory to use the required server’s public key to encrypt the stream every time? I’m not able to visualize. Can you please suggest? – Maverick Apr 22 '20 at 07:05
  • 1
    You have to distribute the server's public key to the client offline somehow, preferably inside its certificate. But I don't know why you aren't just using TLS like everybody else. – user207421 Apr 22 '20 at 10:19
  • 1
    What about using RMI vai SSL/TLS with certificate based client authentication? – Robert Apr 22 '20 at 11:27
  • 2
    No offense, but based on your question you aren't expert enough to roll your own. While it can be done with much pain and insecurity, asymmetric crypto should never be used to encrypt bulk data as you are proposing. I would say use hybrid encryption but as others have noted, this is a solved problem: use RMI over SSL/TLS. It meets your requirements and it's an easy button as well. – President James K. Polk Apr 22 '20 at 16:11
  • I'm a student and this is a university assignment where I have to secure the communications happening over the RMI using RSA cryptography. So, I don't have any choice left. I have to use RSA to encrypt the communications between nodes using their public-private keys. I really appreciate any help in this direction. – Maverick Apr 23 '20 at 21:56
  • [this tutorial](https://www.baeldung.com/java-cipher-input-output-stream) encrypts/decrypts files with AES algorithm ...the algorithm is replaceable & streams are used for en-/decryption (applicable/analogous to your `XOr` streams..) – xerx593 Apr 23 '20 at 23:02
  • "Java allows us to leverage the convenient CipherOutputStream class for writing the encrypted content into another OutputStream." ... CypherInputStream for decryption. – xerx593 Apr 23 '20 at 23:03
  • @xerx593 Not with RMI it doesn't. RMI doesn't provide any opportunity to use input or output streams. Where are you quoting from? And it's `CipherInputStream`, not `CypherInputStream`. – user207421 Apr 24 '20 at 00:24
  • @xerc593 I'm aware of RMI socket factories, and a few other things that might surprise you, but setting one up to use custom streams is extremely non-trivial. 'From the article' is not an adequate response to my question. `String` is not a container for binary data, such as ciphertext, but `SealedObject` is ... which is why I mentioned it. 'Who cares' about how a class name is spelt starts with the compller and extends to anybody who tries to follow your misspelt recommendation. – user207421 Apr 24 '20 at 07:55
  • "RMI doesn't provide any opportunity to use input or output streams", @user207421, have you ever looked into the "question code"? (https://web.mit.edu/java_v1.5.0_22/distrib/share/docs/guide/rmi/socketfactory/index.html) ...that's how ((XOR encryption))! i don't doubt, that you are smart, and have seen many things.... but i doubt, that you are smarter than Maverick's professor (and his chair) ... and yes, the task is not trivial! ...but far beyond from "impossible"... – xerx593 Apr 27 '20 at 10:25
  • I found some (german lang) resource stating, that RSA is by far too inefficient for a "byte-wise" encryption! ..and proposing: to exchange (only) an AES-key via RSA! ...and base the rest of the communication on that AES key (symmetric encryption)... – xerx593 Apr 27 '20 at 10:29
  • ["some resource"](http://codekicker.de/news/Verschluesselung-Java-Streams-AES-RSA) – xerx593 Apr 27 '20 at 11:35
  • @xerx593 Stop it. I've been seeing code that like for 23 years, and I wrote a lot of it for my book on RMI in 2001. The sample code you linked to first doesn't show how to actually write the`XorServerSocket` class, which is the hard part. Your second link merely shows what the Cipher streams look like inside. I have not used the word 'impossible' and it is therefore nothing short of dishonest for you to put it in quotes as though I had. You – user207421 May 04 '20 at 23:31
  • @user207421 I did take a look at how they implemented `XorServerSocket`. One field, one constructor, and `accept()` is overridden with a 3 line method - this can't be the hard part. – Johannes Kuhn May 05 '20 at 00:01
  • @JohannesKuhn It isn't. The hard part is getting the accepted socket to construct the cipher streams. – user207421 Sep 07 '20 at 01:34

1 Answers1

0

I don't know if I should answer my own question.

I tried many approaches but I got exceptions and the nodes were not starting. So, I believe there is not a generic way to secure RMI communications through RSA cryptography for my situations.

So, I tried a different approach.

I changed the method signature of the RMI methods in the interface and implementations from

public void query(MessageID messageID, long TTL, String fileName, String upstreamIP) throws RemoteException

to

public void query(byte[] bytes) throws RemoteException

Now, before every RMI call, I convert the arguments to a custom object and then into bytes, apply the RSA encryption using the sender's private key to convert into encrypted bytes and then pass it to the server.

On the server end, collect the bytes, decrypt them using the sender's RSA public key and then cast to the custom object, extract the information and finally pass to the business logic. This process is done on each RMI call.

This is similar to the sockets, where we write everything into the the stream. Eventually, in the RMI call, the objects which we pass are converted into bytes. So, using this approach I'm explicitly converting them into bytes and then apply the encryption and pass it through RMI. Over the network, it will be transferred as encrypted bytes. This will be for all the RMI calls which includes the messages as well as the file content.

Maverick
  • 1,519
  • 18
  • 32