📄 sslsocket.java
字号:
* * With --> denoting output and <-- denoting input. * denotes optional * messages. * * Alternatively, this may be an abbreviated handshake if we are resuming * a session: * * ClientHello --> * ServerHello <-- * [ChangeCipherSpec] <-- * Finished <-- * [ChangeCipherSpec] --> * Finished --> */ private void doClientHandshake() throws IOException { if (DEBUG_HANDSHAKE_LAYER) { logger.log (Component.SSL_HANDSHAKE, "starting client handshake in {0}", Thread.currentThread()); } IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH); IMessageDigest sha = HashFactory.getInstance(Registry.SHA160_HASH); DigestInputStream din = new DigestInputStream(handshakeIn, md5, sha); DigestOutputStream dout = new DigestOutputStream(handshakeOut, md5, sha); Session continuedSession = null; byte[] sessionId = new byte[0]; List extensions = null; String user = null; CertificateType certType = CertificateType.X509; // Look through the available sessions to see if an appropriate one is // available. for (Enumeration e = sessionContext.getIds(); e.hasMoreElements(); ) { byte[] id = (byte[]) e.nextElement(); continuedSession = (Session) sessionContext.getSession(id); if (continuedSession == null) { continue; } if (!session.enabledProtocols.contains(continuedSession.protocol)) { continue; } if (continuedSession.getPeerHost().equals(remoteHost)) { sessionId = id; break; } } // If a SRP suite is enabled, ask for a username so we can include it // with our extensions list. for (Iterator i = session.enabledSuites.iterator(); i.hasNext(); ) { CipherSuite s = (CipherSuite) i.next(); if (s.getKeyExchange() == "SRP") { extensions = new LinkedList(); user = askUserName(remoteHost); byte[] b = user.getBytes("UTF-8"); if (b.length > 255) { handshakeFailure(); throw new SSLException("SRP username too long"); } extensions.add(new Extension(Extension.Type.SRP, Util.concat(new byte[] { (byte) b.length }, b))); break; } } // If the jessie.fragment.length property is set, add the appropriate // extension to the list. The fragment length is only actually set if // the server responds with the same extension. try { int flen = Integer.parseInt(Util.getSecurityProperty("jessie.fragment.length")); byte[] ext = new byte[1]; if (flen == 512) ext[0] = 1; else if (flen == 1024) ext[0] = 2; else if (flen == 2048) ext[0] = 3; else if (flen == 4096) ext[0] = 4; else throw new NumberFormatException(); if (extensions == null) extensions = new LinkedList(); extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH, ext)); } catch (NumberFormatException nfe) { } // FIXME: set certificate types. // Send the client hello. ProtocolVersion version = session.protocol; Random clientRandom = new Random(Util.unixTime(), session.random.generateSeed(28)); session.protocol = (ProtocolVersion) session.enabledProtocols.last(); List comp = new ArrayList(2); comp.add(CompressionMethod.ZLIB); comp.add(CompressionMethod.NULL); ClientHello clientHello = new ClientHello(session.protocol, clientRandom, sessionId, session.enabledSuites, comp, extensions); Handshake msg = new Handshake(Handshake.Type.CLIENT_HELLO, clientHello); if (DEBUG_HANDSHAKE_LAYER) logger.log (Component.SSL_HANDSHAKE, "{0}", msg); msg.write (dout, version);// recordOutput.setHandshakeAvail(msg.write(dout, version)); dout.flush();// try// {// Thread.sleep(150);// }// catch (InterruptedException ie)// {// } // Receive the server hello. msg = Handshake.read(din); if (DEBUG_HANDSHAKE_LAYER) logger.log (Component.SSL_HANDSHAKE, "{0}", msg); if (msg.getType() != Handshake.Type.SERVER_HELLO) { throwUnexpectedMessage(); } ServerHello serverHello = (ServerHello) msg.getBody(); Random serverRandom = serverHello.getRandom(); version = serverHello.getVersion(); // If we don't directly support the server's protocol version, choose // the highest one we support that is less than the server's version. if (!session.enabledProtocols.contains(version)) { ProtocolVersion v1 = null, v2 = null; for (Iterator it = session.enabledProtocols.iterator(); it.hasNext(); ) { v1 = (ProtocolVersion) it.next(); if (v1.compareTo(version) > 0) break; v2 = v1; } version = v1; } // The server's version is either unsupported by us (unlikely) or the user // has only enabled incompatible versions. if (version == null) { Alert.Description desc = null; if (serverHello.getVersion() == ProtocolVersion.SSL_3) { desc = Alert.Description.HANDSHAKE_FAILURE; } else { desc = Alert.Description.PROTOCOL_VERSION; } Alert alert = new Alert(Alert.Level.FATAL, desc); sendAlert(alert); session.currentAlert = alert; fatal(); throw new AlertException(alert, true); } if (serverHello.getExtensions() != null) { for (Iterator it = serverHello.getExtensions().iterator(); it.hasNext(); ) { Extension e = (Extension) it.next(); if (e.getType() == Extension.Type.MAX_FRAGMENT_LENGTH) { int len = Extensions.getMaxFragmentLength(e).intValue(); session.params.setFragmentLength(len);// recordOutput.setFragmentLength(len);// recordInput.setFragmentLength(len); } else if (e.getType() == Extension.Type.CERT_TYPE) { certType = Extensions.getServerCertType(e); } } } CipherSuite suite = serverHello.getCipherSuite().resolve(version); boolean newSession = true; if (sessionId.length > 0 && Arrays.equals(sessionId, serverHello.getSessionId())) { SecurityParameters params = session.params; SecureRandom random = session.random; session = (Session) continuedSession.clone(); session.params = params; session.random = random; recordInput.setSession(session);// recordOutput.setSession(session); suite = session.cipherSuite; newSession = false; } else { sessionContext.removeSession(new Session.ID(sessionId)); } if (newSession) { session.peerHost = remoteHost; session.sessionId = new Session.ID(serverHello.getSessionId()); session.cipherSuite = suite; } session.params.reset();// session.params.setInMac(null);// session.params.setOutMac(null);// session.params.setInRandom(null);// session.params.setOutRandom(null);// session.params.setInCipher(null);// session.params.setOutCipher(null); session.currentAlert = null; session.valid = true; session.protocol = version; // If the server responded with the same session id that we sent, we // assume that the session will be continued, and skip the bulk of the // handshake. if (newSession) { PublicKey serverKey = null, serverKex = null; KeyPair clientKeys = null, clientKex = null; CertificateRequest certReq; boolean sendKeyExchange = false; BigInteger srp_x = null; IKeyAgreementParty clientKA = null; IncomingMessage in; // used for key agreement protocol exchange OutgoingMessage out = null; if (suite.getKeyExchange() == "SRP") { String password = askPassword(user); if (DEBUG_KEY_EXCHANGE) { logger.log (Component.SSL_KEY_EXCHANGE, "SRP: password read is ''{0}''", password); } byte[] userSrpPassword = password.getBytes("UTF-8"); // instantiate and setup client-side key agreement party clientKA = KeyAgreementFactory.getPartyAInstance(Registry.SRP_TLS_KA); Map clientAttributes = new HashMap(); clientAttributes.put(SRP6KeyAgreement.HASH_FUNCTION, Registry.SHA160_HASH); clientAttributes.put(SRP6KeyAgreement.USER_IDENTITY, user); clientAttributes.put(SRP6KeyAgreement.USER_PASSWORD, userSrpPassword); try { clientKA.init(clientAttributes); // initiate the exchange out = clientKA.processMessage(null); } catch (KeyAgreementException x) { if (DEBUG_KEY_EXCHANGE) { logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x); } throwHandshakeFailure(); } } if (suite.getSignature() != "anon") { msg = Handshake.read(din, certType); if (DEBUG_HANDSHAKE_LAYER) logger.log (Component.SSL_HANDSHAKE, "{0}", msg); if (msg.getType() != Handshake.Type.CERTIFICATE) { throwUnexpectedMessage(); } Certificate serverCertificate = (Certificate) msg.getBody(); X509Certificate[] peerCerts = serverCertificate.getCertificates(); try { session.trustManager.checkServerTrusted(peerCerts, suite.getAuthType()); if (suite.getSignature() == "RSA" && !(peerCerts[0].getPublicKey() instanceof RSAPublicKey)) throw new InvalidKeyException("improper public key"); if (suite.getKeyExchange() == "DH" && !(peerCerts[0].getPublicKey() instanceof DHPublicKey)) throw new InvalidKeyException("improper public key"); if (suite.getKeyExchange() == "DHE") { if (suite.getSignature() == "RSA" && !(peerCerts[0].getPublicKey() instanceof RSAPublicKey)) throw new InvalidKeyException("improper public key"); if (suite.getSignature() == "DSS" && !(peerCerts[0].getPublicKey() instanceof DSAPublicKey)) throw new InvalidKeyException("improper public key"); } session.peerCerts = peerCerts; session.peerVerified = true; } catch (InvalidKeyException ike) { throwHandshakeFailure(); } catch (Exception x) { if (!checkCertificates(peerCerts)) { peerUnverified(peerCerts); SSLPeerUnverifiedException e = new SSLPeerUnverifiedException ("could not verify peer certificate: "+ peerCerts[0].getSubjectDN()); e.initCause (x); throw e; } session.peerCerts = peerCerts; session.peerVerified = true; } serverKey = peerCerts[0].getPublicKey(); serverKex = serverKey; } msg = Handshake.read(din, suite, serverKey); // Receive the server's key exchange. if (msg.getType() == Handshake.Type.SERVER_KEY_EXCHANGE) { if (DEBUG_HANDSHAKE_LAYER) logger.log (Component.SSL_HANDSHAKE, "{0}", msg); ServerKeyExchange skex = (ServerKeyExchange) msg.getBody(); serverKex = skex.getPublicKey(); if (suite.getSignature() != "anon") { ISignature sig = null; if (suite.getSignature() == "RSA") { sig = new SSLRSASignature(); } else if (suite.getSignature() == "DSS") { sig = SignatureFactory.getInstance(Registry.DSS_SIG); } sig.setupVerify(Collections.singletonMap( ISignature.VERIFIER_KEY, serverKey)); byte[] buf = clientRandom.getEncoded(); sig.update(buf, 0, buf.length); buf = serverRandom.getEncoded(); sig.update(buf, 0, buf.length); if (suite.getKeyExchange() == "RSA") { updateSig(sig, ((RSAPublicKey) serverKex).getModulus()); updateSig(sig, ((RSAPublicKey) serverKex).getPublicExponent()); } else if (suite.getKeyExchange() == "DHE") { updateSig(sig, ((DHPublicKey) serverKex).getParams().getP()); updateSig(sig, ((DHPublicKey) serverKex).getParams().getG()); updateSig(sig, ((DHPublicKey) serverKex).getY()); } else if (suite.getKeyExchange() == "SRP") { updateSig(sig, ((SRPPublicKey) serverKex).getN()); updateSig(sig, ((SRPPublicKey) serverKex).getG()); byte[] srpSalt = skex.getSRPSalt(); sig.update((byte) srpSalt.length); sig.update(srpSalt, 0, srpSalt.length); updateSig(sig, ((SRPPublicKey) serverKex).getY()); } if (!sig.verify(skex.getSignature().getSigValue())) { throwHandshakeFailure(); } } if (suite.getKeyExchange() == "SRP") { // use server's key exchange data to continue // agreement protocol by faking a received incoming // message. again the following code can be broken // into multiple blocks for more accurate exception // handling try { out = new OutgoingMessage(); out.writeMPI(((SRPPublicKey) serverKex).getN()); out.writeMPI(((SRPPublicKey) serverKex).getG()); out.writeMPI(new BigInteger(1, skex.getSRPSalt())); out.writeMPI(((SRPPublicKey) serverKex).getY()); in = new IncomingMessage(out.toByteArray()); out = clientKA.processMessage(in); if (DEBUG_KEY_EXCHANGE) { logger.log (Component.SSL_KEY_EXCHANGE, "clientKA isComplete? {0}", Boolean.valueOf (clientKA.isComplete())); } } catch (KeyAgreementException x) { if (DEBUG_KEY_EXCHANGE) { logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -