Private
Public Access
Minamp 1.4: faster connecting
- Remember the connection that worked and try it alone first next start - Prefer plain HTTP on the home network (each TLS handshake costs seconds on a 600 MHz phone); new setting "Encrypt at home too" to keep HTTPS - Try secure addresses one at a time instead of in parallel, so they don't all time out together - TLS 1.2 with session resumption: reconnects skip the full handshake - Cache certificate chains already verified; changing the trusted roots clears that cache and all TLS sessions - README: updated connection order; test: session resumption check and HandshakeProfile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
58d21b6d68
commit
6fd17bc9c5
9 files changed
+284
-67
No files matched your search
@@ -45,14 +45,39 @@ public final class CertVerifier {
|
||||
}
|
||||
|
||||
private static RootStore roots;
|
||||
/** Chains already proven to lead to a trusted root (keyed by a hash of the chain), so a
|
||||
* reconnect only re-checks the host name and dates, not every signature again. */
|
||||
private static final java.util.Set<String> verifiedChains = new java.util.HashSet<String>();
|
||||
|
||||
public static void setRootStore(RootStore store) { roots = store; }
|
||||
/** Changing what's trusted invalidates everything trusted so far: cached chains and TLS sessions. */
|
||||
public static void setRootStore(RootStore store) {
|
||||
roots = store;
|
||||
synchronized (verifiedChains) { verifiedChains.clear(); }
|
||||
Http.forgetSessions();
|
||||
}
|
||||
|
||||
private CertVerifier() {}
|
||||
|
||||
|
||||
public static void verify(List<byte[]> chainDer, String host) throws IOException {
|
||||
if (chainDer == null || chainDer.isEmpty()) throw new IOException("Server sent no certificate");
|
||||
if (roots == null) throw new IOException("No trust store configured");
|
||||
java.io.ByteArrayOutputStream all = new java.io.ByteArrayOutputStream();
|
||||
for (int i = 0; i < chainDer.size(); i++) all.write(chainDer.get(i), 0, chainDer.get(i).length);
|
||||
String chainKey = sha1Hex(all.toByteArray());
|
||||
boolean known;
|
||||
synchronized (verifiedChains) { known = verifiedChains.contains(chainKey); }
|
||||
if (known) {
|
||||
Certificate leaf = Certificate.getInstance(chainDer.get(0));
|
||||
if (!hostMatches(leaf, host)) throw new IOException("Certificate does not match " + host);
|
||||
if (new Date().getTime() > 1704067200000L) checkDates(leaf, new Date());
|
||||
return;
|
||||
}
|
||||
verifyFully(chainDer, host);
|
||||
synchronized (verifiedChains) { verifiedChains.add(chainKey); }
|
||||
}
|
||||
|
||||
private static void verifyFully(List<byte[]> chainDer, String host) throws IOException {
|
||||
List<Certificate> chain = new ArrayList<Certificate>();
|
||||
for (int i = 0; i < chainDer.size(); i++) chain.add(Certificate.getInstance(chainDer.get(i)));
|
||||
|
||||
|
||||
Reference in new issue
Block a user