Reputation: 1973
I want to implement a small android application, that works as SSL Server. After lot of problems with the right format of the keystore, I solved this and run into the next one.
My keystore file is properly loaded by the KeyStore class. But when I try to open the server socket (socket.accept()) the following error is raised:
javax.net.ssl.SSLException: Could not find any key store entries to support the enabled cipher suites.
I generated my keystore with this command:
keytool -genkey -keystore test.keystore -keyalg RSA -keypass ssltest -storepass ssltest -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov.jar
with the Unlimited Strength Jurisdiction Policy for Java SE6 applied to my jre6.
I got a list of supported ciphers suites by calling
socket.getSupportedCipherSuites()
that prints a long list with very different combinations. But I don't know how to get a supported key. I also tried the android debug keystore after converting it to BKS format using portecle but get still the same error.
Can anyone help and tell how I can generate a key that is compatible with one of the cipher suites?
Version Information:
targetSDK: 15
tested on emulator running 4.0.3 and real device running 2.3.3
BounceCastle 1.46
portecle 1.7
Code of my test application:
public class SSLTestActivity extends Activity implements Runnable {
SSLServerSocket mServerSocket;
ToggleButton tglBtn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.tglBtn = (ToggleButton)findViewById(R.id.toggleButton1);
tglBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
new Thread(SSLTestActivity.this).run();
} else {
try {
if (mServerSocket != null)
mServerSocket.close();
} catch (IOException e) {
Log.e("SSLTestActivity", e.toString());
}
}
}
});
}
@Override
public void run() {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(getAssets().open("test.keystore"), "ssltest".toCharArray());
ServerSocketFactory socketFactory = SSLServerSocketFactory.getDefault();
mServerSocket = (SSLServerSocket) socketFactory.createServerSocket(8080);
while (!mServerSocket.isClosed()) {
Socket client = mServerSocket.accept();
PrintWriter output = new PrintWriter(client.getOutputStream(), true);
output.println("So long, and thanks for all the fish!");
client.close();
}
} catch (Exception e) {
Log.e("SSLTestActivity", e.toString());
}
}
}
Upvotes: 0
Views: 3029
Reputation: 51
This might come too late for you but for others along the ways.
keytool -genkey -keystore test.keystore -keyalg RSA -keypass ssltest -storepass ssltest -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov.jar
created the keypair successfully and in theory should worked.
What I am not sure of is the content of the keypair. If you had left everything as the default (ie enter enter all the way), the CN will be of value "Unknown". I ran through a few iteration of test and confirm it. CN=Unknown will generate keypair successfully (Can confirm that with Keytool -list) but will fail during the the SSL negotiation. Somehow it will fail to find the key required to establish the secure connection. (The below will fail with the above mentioned exception)
File: C:\Users\James\Downloads\test.keystore Type: BKS-V1 Provider: BC Keys None Key Pairs mykey Last Modified: 07/Aug/2015 16:07:13 ICT Private Key Locked - unlock to get properties Certificates Unknown Version: 3 Subject: CN=Unknown,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown Issuer: CN=Unknown,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown Serial Number: 5BA77D0F Valid From: 07/Aug/2015 16:07:13 ICT Valid Until: 05/Nov/2015 16:07:13 ICT Public Key Algorithm: RSA Key Size: 2048 bits Format: X.509 Encoded: 0x30820122300D06092A864886F70D01010105000382010F003082010A02820101009344283AD35606471D23D2F2B4DA61614C9A973932DF798DF66FE034C818BD6B0285BE860894FBD750180E2D668123442652D04BDFA6190CC28DBB2AA5EB657A428880428226D45F5B942AAB71FF05890FC4CD9A9F932F70E84A5CC118215E7FFE4C93FEFE46E8BD4B141D1742C790BACFF7B503230E263419A23BA3E8B4E7E0F4AECDF5082363AA86693502FFBAA3545F87AE7E462139CF666B35BF348CB5E61F2A62BEBA019F3C51021890A6D58093E91E6B807257DDF138BBB1044B8EB44A8F1E835A04B5EA3C53A7F024C805F28C1A28DFD12A2AC9A1335FD220AD247D951385756964DA1EDD804A13B42B6006554525954EEEBBCFD35FA0D81C93E0DEE50203010001 Public Exponent: 0x10001 Modulus: 0x9344283AD35606471D23D2F2B4DA61614C9A973932DF798DF66FE034C818BD6B0285BE860894FBD750180E2D668123442652D04BDFA6190CC28DBB2AA5EB657A428880428226D45F5B942AAB71FF05890FC4CD9A9F932F70E84A5CC118215E7FFE4C93FEFE46E8BD4B141D1742C790BACFF7B503230E263419A23BA3E8B4E7E0F4AECDF5082363AA86693502FFBAA3545F87AE7E462139CF666B35BF348CB5E61F2A62BEBA019F3C51021890A6D58093E91E6B807257DDF138BBB1044B8EB44A8F1E835A04B5EA3C53A7F024C805F28C1A28DFD12A2AC9A1335FD220AD247D951385756964DA1EDD804A13B42B6006554525954EEEBBCFD35FA0D81C93E0DEE5 Signature Algorithm: SHA256WITHRSA MD5 Fingerprint: 47:F8:40:B9:05:71:CF:30:36:8D:B4:28:7D:FE:B7:6F SHA-1 Fingerprint: 11:6F:A3:28:7F:87:97:E7:14:CE:63:A1:9D:09:85:CF:E4:7E:FE:E8 Trusted Certificates None
BTW: For Windows Dev, you might want to consider Key Explorer as compare to Keytool. It has more functionality than Keytool.
Upvotes: 0
Reputation: 122669
Keystore does not support enabled cipher suites
It's not really up to the keystore to support or not a cipher suite. It's the SSLSocket
(or engine) that supports them. What it's looking for is a key, in the keystore, of a type suitable for one of its supported cipher suites. Typically, enabled cipher suites are RSA or DSS based, so it will look for an RSA or DSA key respectively.
In the following code:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(getAssets().open("test.keystore"), "ssltest".toCharArray());
ServerSocketFactory socketFactory = SSLServerSocketFactory.getDefault();
mServerSocket = (SSLServerSocket) socketFactory.createServerSocket(8080);
You're not doing anything with your keyStore
. You might as well not load it at all in this case (and you should always close the input stream you read from, by the way).
Here, you're still using the default SSLServerSocketFactory
, which you haven't specifically configured (and for which there is no default keystore): this is why you get "Could not find any key store entries to support the enabled cipher suites": it can't find a suitable key store entry, because it can't even find the key store.
You would need to configure an SSLContext
, initialise it with a KeyManager
built from your keystore and then get a server socket factory from it.
Upvotes: 2