我正在尝试使用充气城堡DTLS Handshake
。
我已经按照这个链接生成了密钥。我正在通过扩展 DefaultTlsClient 来工作。它可以生成client_hello包。但是当 server_hello 数据包到达时,它给出了org.bouncycastle.crypto.tls.TlsFatalAlert: internal_error(80)
Caused by: java.lang.IllegalArgumentException: unknown HashAlgorithm
。任何人都可以给出任何提示吗?
更新:
来自 Wireshark:在证书请求中,有 9 个签名哈希算法。其中之一是rsa_pss_sha256(0x0804)
。在public static Digest createHash(short hashAlgorithm)
函数中TlsUtils.java
没有匹配它。这就是它给出未知哈希算法的原因。这意味着什么?使用 Bouncy Castle,是否可以与该服务器建立 DTLS?
这是加载密钥库的代码:
public static void initKeyStore() {
char password[] = "bbtone".toCharArray();
if( !isKeystoreLoaded) {
try {
FileInputStream fis = new FileInputStream("bbtone");
KeyMgmt key = new KeyMgmt();
key.open(fis, password);
fis.close();
crt = key.getCRT("bbtone").getEncoded();
fingerprintSHA256 = KeyMgmt.fingerprintSHA256(crt);
ArrayList<byte[]> chain = new ArrayList<byte[]>();
chain.add(crt);
java.security.cert.Certificate root = key.getCRT("root");
if (root != null) {
chain.add(root.getEncoded());
}
privateKey = key.getKEY("bbtone", password).getEncoded();
initDTLS(chain, privateKey, false);
isKeystoreLoaded = true;
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
}
}
生成私钥和证书:
public static boolean initDTLS(java.util.List<byte []> certChain, byte privateKey[], boolean pkRSA) {
try {
org.bouncycastle.asn1.x509.Certificate x509certs[] = new org.bouncycastle.asn1.x509.Certificate[certChain.size()];
for (int i = 0; i < certChain.size(); ++i) {
x509certs[i] = org.bouncycastle.asn1.x509.Certificate.getInstance(certChain.get(i));
}
dtlsCertChain = new org.bouncycastle.crypto.tls.Certificate(x509certs);
if (pkRSA) {
RSAPrivateKey rsa = RSAPrivateKey.getInstance(privateKey);
dtlsPrivateKey = new RSAPrivateCrtKeyParameters(rsa.getModulus(), rsa.getPublicExponent(),
rsa.getPrivateExponent(), rsa.getPrime1(), rsa.getPrime2(), rsa.getExponent1(),
rsa.getExponent2(), rsa.getCoefficient());
} else {
dtlsPrivateKey = PrivateKeyFactory.createKey(privateKey);
}
return true;
} catch (Exception e) {
return false;
}
}
开始 DTLS 握手:
public void startDTLS() {
socket.connect(recvPacket.getAddress(), recvPacket.getPort());
try {
dtlsClient = new DTLSClientProtocol(new SecureRandom());
} catch (Exception e) {
e.printStackTrace();
dtlsClient = null;
return;
}
tlsClient = new DefaultTlsClient2() {
protected TlsSession session;
public TlsSession getSessionToResume()
{
return this.session;
}
public ProtocolVersion getClientVersion() {
return ProtocolVersion.DTLSv12;
}
public ProtocolVersion getMinimumVersion() {
return ProtocolVersion.DTLSv10;
}
public Hashtable getClientExtensions() throws IOException {
//see : http://bouncy-castle.1462172.n4.nabble.com/DTLS-SRTP-with-bouncycastle-1-49-td4656286.html
logger.debug("Extending getClientExtensions\n");
Hashtable table = super.getClientExtensions();
if (table == null) table = new Hashtable();
//adding the protection profiles
int[] protectionProfiles = {
SRTPProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_80 //this is the only one supported for now
// SRTPProtectionProfile.SRTP_AES128_CM_HMAC_SHA1_32
// SRTPProtectionProfile.SRTP_NULL_HMAC_SHA1_32
// SRTPProtectionProfile.SRTP_NULL_HMAC_SHA1_80
};
byte mki[] = new byte[0]; //do not use mki
UseSRTPData srtpData = new UseSRTPData(protectionProfiles, mki);
TlsSRTPUtils.addUseSRTPExtension(table, srtpData);
return table;
}
public TlsAuthentication getAuthentication() throws IOException {
return new TlsAuthentication() {
public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate)
throws IOException
{
//info only
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
throws IOException
{
short[] certificateTypes = certificateRequest.getCertificateTypes();
if (certificateTypes == null) return null;
boolean ok = false;
for(int a=0;a<certificateTypes.length;a++) {
if (certificateTypes[a] == ClientCertificateType.rsa_sign) {
ok = true;
break;
}
}
if (!ok) return null;
SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
Vector sigAlgs = certificateRequest.getSupportedSignatureAlgorithms();
if (sigAlgs != null)
{
for (int i = 0; i < sigAlgs.size(); ++i)
{
SignatureAndHashAlgorithm sigAlg = (SignatureAndHashAlgorithm) sigAlgs.elementAt(i);
if (sigAlg.getSignature() == SignatureAlgorithm.rsa)
{
signatureAndHashAlgorithm = sigAlg;
break;
}
}
if (signatureAndHashAlgorithm == null)
{
return null;
}
}
return new DefaultTlsSignerCredentials(context, dtlsCertChain, dtlsPrivateKey, signatureAndHashAlgorithm);
}
};
}
public void notifyHandshakeComplete() throws IOException
{
logger.debug("SRTPChannel:DTLS:Client:Handshake complete");
super.notifyHandshakeComplete();
TlsSession newSession = context.getResumableSession();
if (newSession != null)
{
this.session = newSession;
}
getKeys();
}
};
try {
logger.debug("SRTPChannel:connecting to DTLS server");
dtlsTransport = dtlsClient.connect(tlsClient, new UDPTransport(socket, 1500 - 20 - 8));
} catch (Exception e) {
e.printStackTrace();
}
}
错误:
org.bouncycastle.crypto.tls.TlsFatalAlert: internal_error(80)
at org.bouncycastle.crypto.tls.DTLSClientProtocol.connect(DTLSClientProtocol.java:75)
at processor.ClientMediaHandler.startDTLS(ClientMediaHandler.java:459)
at processor.ClientMediaHandler.run(ClientMediaHandler.java:538)
Caused by: java.lang.IllegalArgumentException: unknown HashAlgorithm
at org.bouncycastle.crypto.tls.TlsUtils.createHash(TlsUtils.java:1184)
at org.bouncycastle.crypto.tls.DeferredHash.checkTrackingHash(DeferredHash.java:203)
at org.bouncycastle.crypto.tls.DeferredHash.trackHashAlgorithm(DeferredHash.java:68)
at org.bouncycastle.crypto.tls.TlsUtils.trackHashAlgorithms(TlsUtils.java:1358)
at org.bouncycastle.crypto.tls.DTLSClientProtocol.clientHandshake(DTLSClientProtocol.java:241)
at org.bouncycastle.crypto.tls.DTLSClientProtocol.connect(DTLSClientProtocol.java:60)
... 2 more