3

Entire code is quire complicated so I am directly coming to the point. Code is as follows

SSLContext ctx = SSLContext.getInstance("TLS");

If you read docs for getInstance(String protocol) method it says

This method traverses the list of registered security Providers, starting
with the most preferred Provider. A new SSLContext object encapsulating
the SSLContextSpi implementation from the first Provider that supports the
specified protocol is returned.

Note that the list of registered providers may be retrieved via the
Security.getProviders() method.

For me Security.getProviders() method gives following providers

enter image description here

Now I have verified that "TLS" protocol is in com.sun.net.ssl.internal.ssl.Provider (index 2 ) and is always selected.

But the corresponding SSLContextSpi object is coming different in Java 6 and Java 7. In java 6 I am getting com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9 and in java 7 I am getting sun.security.ssl.SSLContextImpl$TLS10Context@615ece16. This is having very bad effect as when later I am creating SSL socket they are of different class.

So why is this happening? Is there a work around? I want the same com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9 SSLContextSpi object encapsulated in com.sun.net.ssl.internal.ssl.Provider context(which is same in both cases).

Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289

1 Answers1

5

This is having very bad effect as when later I am creating SSL socket they are of different class.

This is not a bad effect. Which actual class you get from the factories in the public API is at the discretion of the JRE implementation: these concrete classes are not part of the public API.

The fact that you get different classes between Java 6 and Java 7 doesn't really matter. Even if they had the same name, if wouldn't make sense to compare them to one another.

EDIT:

public int read(byte[] b) function reads only 1 bytes when I give it a byte array of length 4 and also i have confirmed that there are 4 bytes in the stream.

SSLSocket in Java 7 is behaving correctly when you get this. In fact, it's probably behaving better, since this initial 1-byte read is due to the BEAST-prevention measure. I'll copy and paste my own answer to that question, since you're making exactly the same mistake.


The assumption you're making about reading the byte[] exactly as you write them on the other end is a classic TCP mistake. It's not actually specific to SSL/TLS, but could also happen with a TCP connection.

There is no guarantee in TCP (and in SSL/TLS) that the reader's buffer will be filled with the exact same packet length as the packets in the writer's buffer. All TCP guarantees is in-order delivery, so you'll eventually get all your data, but you have to treat it as a stream.

This is why protocols that use TCP rely on indicators and delimiters to tell the other end when to stop reading certain messages.

For example, HTTP 1.1 uses a blank line to indicate when the headers end, and it uses the Content-Length header to tell the recipient what entity length to expect (or chunked transfer encoding). SMTP also uses line returns and . at the end of a message.

If you're designing your own protocol, you need to define a way for the recipient to know when what you define as meaningful units of data are delimited. When you read the data, read such indicators, and fill in your read buffer until you get the amount of bytes you expect or until you find the delimiter that you've defined.

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • Problem is that with the socket implementation I get from the class corresponding to java 7 has faulty I/O stream bytes write API. – Aniket Thakur Sep 17 '13 at 19:43
  • 1
    What do you mean by "faulty"? Why would the problem come from this particular implementation? – Bruno Sep 17 '13 at 19:48
  • 1
    @AniketThakur That is vanishingly unlikely, and even if true wouldn't be accounted for by a mere change of class name between versions. I suggest you post the *actual* problem you are having, instead of what arises out of this irrelevant investigation. – user207421 Sep 17 '13 at 21:49
  • @EJP the **public int read(byte[] b)** function reads only 1 bytes when I give it a byte array of length 4 and also i have confirmed that there are 4 bytes in the stream. – Aniket Thakur Sep 18 '13 at 07:22
  • 1
    You have confirmed it *how?* The data in the stream is encrypted: how did you overcome that issue? And in any case there is no guarantee anywhere that 'read()' fills the buffer *or* delivers all the data that is available. If your code depends on that assumption, it is incorrect. Period. – user207421 Sep 18 '13 at 09:38
  • @EJP **You have confirmed it how?** At runtime after reading once in which I received 1 byte I went to evaluate expression and executed the same read operation again. As you know the return value of read operation is the number of bytes read. At this time I received the remaining 3 bytes. Finally as a work around I have put read in while statement(until all n bytes are read). Now it works fine. I am pretty sure it's java library implementation bug. – Aniket Thakur Sep 18 '13 at 14:08
  • Also .available() method gives you the available bytes on the input stream. But it gives ambiguous answers. As for your question about confirmation I simple read again and checked the return value. – Aniket Thakur Sep 18 '13 at 14:10
  • Read my edit: it's not a bug, it's done on purpose. You *always* have to assume there is more to read anyway. Knowing when to stop reading should be indicated by delimiters or length given in the content. This is a general TCP aspect, independently of the language. If you expect 4 bytes, loop and keep reading until you've read those 4 bytes. – Bruno Sep 18 '13 at 14:15
  • There is nothing here that confirms your assertion that there were four bytes available for reading the first time. The fact that available() disagreed with you may also be significant, although it isn't necessarily reliable over SSL anyway. – user207421 Sep 19 '13 at 00:53