I'm trying to connect client and server with the same keystore . The client socket can get peer cert,while the server socket can't get peer cert but port. It failed to get cert and reported abnormal of SSLPeerUnverifiedException. Modified problems confused me several days,pls help to solve it,thanks
my android code is as follows:
client:
java.security.Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider());
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(getKeyManagers(), {new DummyTrustManager()}, null);
SocketFactory socketFactory = sslcontext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket("127.0.0.1", 8080);
socket.getSession().getLocalCertificates();
socket.getSession().getPeerHost();
socket.getSession().getPeerPort();
socket.getSession().getPeerCertificates();`
server:
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(getKeyManagers(), {new DummyTrustManager()}, null);
ServerSocketFactory mFactory = sslcontext.getServerSocketFactory();
ServerSocket serverSocket =mFactory.createServerSocket(8080);
SSLSocket clientSocket = serverSocket.accept();
socket.getSession().getLocalCertificates();
socket.getSession().getPeerHost();
socket.getSession().getPeerPort();
socket.getSession().getPeerCertificates();`
TrustManager:
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class DummyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) {
// Does not throw CertificateException: all chains trusted
return;
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
// Does not throw CertificateException: all chains trusted
return;
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
KeyStore :
public void initializeKeyStore(String id) {
try {
Log.v(LOG_TAG, "Generating key pair ...");
KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = kg.generateKeyPair();
Log.v(LOG_TAG, "Generating certificate ...");
String name = getCertificateName(id);
X509Certificate cert = SslUtil.generateX509V3Certificate(keyPair, name);
Certificate[] chain = {cert};
Log.v(LOG_TAG, "Adding key to keystore ...");
mKeyStore.setKeyEntry(
LOCAL_IDENTITY_ALIAS, keyPair.getPrivate(), null, chain);
Log.d(LOG_TAG, "Key added!");
} catch (GeneralSecurityException e) {
throw new IllegalStateException("Unable to create identity KeyStore", e);
}
store(mKeyStore);}
public synchronized KeyManager[] getKeyManagers()
throws GeneralSecurityException {
if (mKeyStore == null) {
throw new NullPointerException("null mKeyStore");
}
KeyManagerFactory factory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
factory.init(mKeyStore, "".toCharArray());
return factory.getKeyManagers();
}
cert:
public static X509Certificate generateX509V3Certificate(KeyPair pair,
String name) throws GeneralSecurityException {
Calendar calendar = Calendar.getInstance();
calendar.set(2009, 0, 1);
Date notBefore = new Date(calendar.getTimeInMillis());
calendar.set(2099, 0, 1);
Date notAfter = new Date(calendar.getTimeInMillis());
BigInteger serialNumber = BigInteger.valueOf(Math.abs(
System.currentTimeMillis()));
return generateX509V3Certificate(pair, name, notBefore, notAfter,
serialNumber);
}
public static X509Certificate generateX509V3Certificate(KeyPair pair,
String name, Date notBefore, Date notAfter, BigInteger serialNumber)
throws GeneralSecurityException {
java.security.Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider());
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X509Name dnName = new X509Name(name);
certGen.setSerialNumber(serialNumber);
certGen.setIssuerDN(dnName);
certGen.setSubjectDN(dnName); // note: same as issuer
certGen.setNotBefore(notBefore);
certGen.setNotAfter(notAfter);
certGen.setPublicKey(pair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
certGen.addExtension(X509Extensions.BasicConstraints, true,
new BasicConstraints(false));
certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature
| KeyUsage.keyEncipherment | KeyUsage.keyCertSign));
certGen.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(
KeyPurposeId.id_kp_serverAuth));
AuthorityKeyIdentifier authIdentifier = createAuthorityKeyIdentifier(
pair.getPublic(), dnName, serialNumber);
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, true,
authIdentifier);
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, true,
new SubjectKeyIdentifierStructure(pair.getPublic()));
certGen.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(
new GeneralName(GeneralName.rfc822Name, "googletv@test.test")));
// This method is deprecated, but Android Eclair does not provide the
// generate() methods.
X509Certificate cert = certGen.generateX509Certificate(pair.getPrivate(), "BC");
return cert;
}
enter code here
You probably need to call SSLServerSocket.setNeedClientAuth()
to have the server side require client authentication. The client will then send its certificate, and you should be able to get it with getPeerCertificates()
.
Reference:
I'm trying to connect client and server with the same keystore
That's only a valid thing to do it the client entity and the server entity are really the same legal entity.
If not, you are certainly barking up the wrong tree entirely, in a way which has very profound legal ramifications. I suggest you seek advice from the business/legal side before continuing.