- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在开发一种分析某些 SSL 服务的工具,现在我正在尝试测试客户端启动的重新协商。
我正在使用 BouncyCaSTLe 来执行此操作,使用带有自定义函数的 TlsClientProtocol,因为 BC 本身不会“处理”重新协商。
所以,现在我正在使用这个类:
package org.bouncycastle.crypto.tls;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Hashtable;
import org.bouncycastle.crypto.tls.Certificate;
import org.bouncycastle.crypto.tls.CipherSuite;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.ExtensionType;
import org.bouncycastle.crypto.tls.ServerOnlyTlsAuthentication;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.util.encoders.Hex;
/**
*
* @version 1.0
*/
public class TestProtocol extends TlsClientProtocol {
private byte[] verifyData;
public TestProtocol(InputStream input, OutputStream output) {
super(input, output);
}
// I need to replace this method to have the verifyData,
// because we need to send it into the renegotiation_info ext
@Override
protected void sendFinishedMessage() throws IOException {
verifyData = createVerifyData(getContext().isServer());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
TlsUtils.writeUint8(HandshakeType.finished, bos);
TlsUtils.writeUint24(verifyData.length, bos);
bos.write(verifyData);
byte[] message = bos.toByteArray();
safeWriteRecord(ContentType.handshake, message, 0, message.length);
}
public void renegotiate() throws IOException {
this.connection_state = CS_START;
sendClientHelloMessage();
this.connection_state = CS_CLIENT_HELLO;
completeHandshake();
}
public static void main(String[] args) throws IOException, InterruptedException {
Socket s = new Socket("10.0.0.101", 443);
final TestProtocol proto = new TestProtocol(s.getInputStream(), s.getOutputStream());
proto.connect(new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
return new ServerOnlyTlsAuthentication() {
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {}
};
}
@Override
public int[] getCipherSuites() {
return new int[]{CipherSuite.TLS_RSA_WITH_NULL_SHA, CipherSuite.TLS_RSA_WITH_NULL_MD5};
}
private boolean first = true;
@Override
public Hashtable getClientExtensions() throws IOException {
@SuppressWarnings("unchecked")
Hashtable<Integer, byte[]> clientExtensions = super.getClientExtensions();
if (clientExtensions == null) {
clientExtensions = new Hashtable<Integer, byte[]>();
}
// If this is the first ClientHello, we're not doing anything
if (first) {
first = false;
}
else {
// If this is the second, we add the renegotiation_info extension
byte[] ext = new byte[proto.verifyData.length + 1];
ext[0] = (byte) proto.verifyData.length;
System.arraycopy(proto.verifyData, 0, ext, 1, proto.verifyData.length);
clientExtensions.put(ExtensionType.renegotiation_info, ext);
}
clientExtensions.put(ExtensionType.session_ticket, new byte[] {});
return clientExtensions;
}
});
proto.renegotiate();
}
}
它正在工作..几乎..
当我调用 renegotiate() 方法时,它:
- 发送 ClientHello
- 接收 ServerHello
- 收到证书
- 接收 ServerHelloDone
- 发送 ClientKeyExchange
- 发送 ChangeCipherSpec
- 发送完成
- 收到警报:致命,解密错误;而不是 NewSessionTicket、ChangeCipherSpec、Finish
我只是想不通为什么。我认为它可能是用于创建需要刷新的 MAC 的 SeqNumber,但不是。当我给出明显错误的值时,我还会收到 MAC 错误警报。
为了进行测试,我使用了一个允许 CLEAR 密码套件并且显然允许客户端启动的重新协商的服务器。
当我尝试使用 OpenSSL 时,它工作正常,但我看不出有什么不同,我做错了什么。
服务器位于私有(private) VPN 上,因此您不能用它来测试东西,但这里是握手的 .cap。
https://stuff.stooit.com/d/1/528b4a314e35d/openssl.cap
https://stuff.stooit.com/d/1/528b4a54a68cd/my.cap
第一个是工作的,使用 openSSL。第二个是我的,使用的是 BouncyCaSTLe。
我知道在这个案子上帮助我不是一件容易的事,但是嘿,感谢那些会尝试的人:)
最佳答案
好吧,一如既往,我在发布问题后几次就找到了答案——(即使我花了几个小时/几天)。
问题来自客户端发送的“已完成”消息。 verify_data 是包含当前协商的所有先前握手消息的哈希。
但在我的例子中,它还包含第一次协商的握手消息,因此 verify_data 没有很好的值(value)。
为了让它工作,我需要重置 RecordStream.hash
,使用 RecordStream.hash.reset()
关于java - TLS 服务返回警报 :decrypt_error when renegotiating,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20069799/
我正在开发一种分析某些 SSL 服务的工具,现在我正在尝试测试客户端启动的重新协商。 我正在使用 BouncyCaSTLe 来执行此操作,使用带有自定义函数的 TlsClientProtocol,因为
我是一名优秀的程序员,十分优秀!