📄 tlsprotocolhandler.java
字号:
package org.bouncycastle.crypto.tls;import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;import org.bouncycastle.crypto.InvalidCipherTextException;import org.bouncycastle.crypto.encodings.PKCS1Encoding;import org.bouncycastle.crypto.engines.RSABlindedEngine;import org.bouncycastle.crypto.params.ParametersWithRandom;import org.bouncycastle.crypto.params.RSAKeyParameters;import org.bouncycastle.crypto.prng.ThreadedSeedGenerator;import org.bouncycastle.util.BigIntegers;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.math.BigInteger;import java.security.SecureRandom;/** * An implementation of all high level protocols in TLS 1.0. */public class TlsProtocolHandler{ private static final short RL_CHANGE_CIPHER_SPEC = 20; private static final short RL_ALERT = 21; private static final short RL_HANDSHAKE = 22; private static final short RL_APPLICATION_DATA = 23; /* hello_request(0), client_hello(1), server_hello(2), certificate(11), server_key_exchange (12), certificate_request(13), server_hello_done(14), certificate_verify(15), client_key_exchange(16), finished(20), (255) */ private static final short HP_HELLO_REQUEST = 0; private static final short HP_CLIENT_HELLO = 1; private static final short HP_SERVER_HELLO = 2; private static final short HP_CERTIFICATE = 11; private static final short HP_SERVER_KEY_EXCHANGE = 12; private static final short HP_CERTIFICATE_REQUEST = 13; private static final short HP_SERVER_HELLO_DONE = 14; private static final short HP_CERTIFICATE_VERIFY = 15; private static final short HP_CLIENT_KEY_EXCHANGE = 16; private static final short HP_FINISHED = 20; /* * Our Connection states */ private static final short CS_CLIENT_HELLO_SEND = 1; private static final short CS_SERVER_HELLO_RECEIVED = 2; private static final short CS_SERVER_CERTIFICATE_RECEIVED = 3; private static final short CS_SERVER_KEY_EXCHANGE_RECEIVED = 4; private static final short CS_CERTIFICATE_REQUEST_RECEIVED = 5; private static final short CS_SERVER_HELLO_DONE_RECEIVED = 6; private static final short CS_CLIENT_KEY_EXCHANGE_SEND = 7; private static final short CS_CLIENT_CHANGE_CIPHER_SPEC_SEND = 8; private static final short CS_CLIENT_FINISHED_SEND = 9; private static final short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 10; private static final short CS_DONE = 11; protected static final short AP_close_notify = 0; protected static final short AP_unexpected_message = 10; protected static final short AP_bad_record_mac = 20; protected static final short AP_decryption_failed = 21; protected static final short AP_record_overflow = 22; protected static final short AP_decompression_failure = 30; protected static final short AP_handshake_failure = 40; protected static final short AP_bad_certificate = 42; protected static final short AP_unsupported_certificate = 43; protected static final short AP_certificate_revoked = 44; protected static final short AP_certificate_expired = 45; protected static final short AP_certificate_unknown = 46; protected static final short AP_illegal_parameter = 47; protected static final short AP_unknown_ca = 48; protected static final short AP_access_denied = 49; protected static final short AP_decode_error = 50; protected static final short AP_decrypt_error = 51; protected static final short AP_export_restriction = 60; protected static final short AP_protocol_version = 70; protected static final short AP_insufficient_security = 71; protected static final short AP_internal_error = 80; protected static final short AP_user_canceled = 90; protected static final short AP_no_renegotiation = 100; protected static final short AL_warning = 1; protected static final short AL_fatal = 2; private static final byte[] emptybuf = new byte[0]; private static final String TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack"; /* * Queues for data from some protocols. */ private ByteQueue applicationDataQueue = new ByteQueue(); private ByteQueue changeCipherSpecQueue = new ByteQueue(); private ByteQueue alertQueue = new ByteQueue(); private ByteQueue handshakeQueue = new ByteQueue(); /* * The Record Stream we use */ private RecordStream rs; private SecureRandom random; /* * The public rsa-key of the server. */ private RSAKeyParameters serverRsaKey = null; private TlsInputStream tlsInputStream = null; private TlsOuputStream tlsOutputStream = null; private boolean closed = false; private boolean failedWithError = false; private boolean appDataReady = false; private byte[] clientRandom; private byte[] serverRandom; private byte[] ms; private TlsCipherSuite chosenCipherSuite = null; private BigInteger Yc; private byte[] pms; private CertificateVerifyer verifyer = null; public TlsProtocolHandler(InputStream is, OutputStream os) { /* * We use our threaded seed generator to generate a good random * seed. If the user has a better random seed, he should use * the constructor with a SecureRandom. */ ThreadedSeedGenerator tsg = new ThreadedSeedGenerator(); this.random = new SecureRandom(); /* * Hopefully, 20 bytes in fast mode are good enough. */ this.random.setSeed(tsg.generateSeed(20, true)); this.rs = new RecordStream(this, is, os); } public TlsProtocolHandler(InputStream is, OutputStream os, SecureRandom sr) { this.random = sr; this.rs = new RecordStream(this, is, os); } private short connection_state; protected void processData(short protocol, byte[] buf, int offset, int len) throws IOException { /* * Have a look at the protocol type, and add it to the correct queue. */ switch (protocol) { case RL_CHANGE_CIPHER_SPEC: changeCipherSpecQueue.addData(buf, offset, len); processChangeCipherSpec(); break; case RL_ALERT: alertQueue.addData(buf, offset, len); processAlert(); break; case RL_HANDSHAKE: handshakeQueue.addData(buf, offset, len); processHandshake(); break; case RL_APPLICATION_DATA: if (!appDataReady) { this.failWithError(AL_fatal, AP_unexpected_message); } applicationDataQueue.addData(buf, offset, len); processApplicationData(); break; default: /* * Uh, we don't know this protocol. * * RFC2246 defines on page 13, that we should ignore this. */ } } private void processHandshake() throws IOException { boolean read; do { read = false; /* * We need the first 4 bytes, they contain type and length of * the message. */ if (handshakeQueue.size() >= 4) { byte[] beginning = new byte[4]; handshakeQueue.read(beginning, 0, 4, 0); ByteArrayInputStream bis = new ByteArrayInputStream(beginning); short type = TlsUtils.readUint8(bis); int len = TlsUtils.readUint24(bis); /* * Check if we have enough bytes in the buffer to read * the full message. */ if (handshakeQueue.size() >= (len + 4)) { /* * Read the message. */ byte[] buf = new byte[len]; handshakeQueue.read(buf, 0, len, 4); handshakeQueue.removeData(len + 4); /* * If it is not a finished message, update our hashes * we prepare for the finish message. */ if (type != HP_FINISHED) { rs.hash1.update(beginning, 0, 4); rs.hash2.update(beginning, 0, 4); rs.hash1.update(buf, 0, len); rs.hash2.update(buf, 0, len); } /* * Now, parse the message. */ ByteArrayInputStream is = new ByteArrayInputStream(buf); /* * Check the type. */ switch (type) { case HP_CERTIFICATE: switch (connection_state) { case CS_SERVER_HELLO_RECEIVED: /* * Parse the certificates. */ Certificate cert = Certificate.parse(is); assertEmpty(is); /* * Verify them. */ if (!this.verifyer.isValid(cert.getCerts())) { this.failWithError(AL_fatal, AP_user_canceled);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -