I’m working on an embedded Android TV project. I’m using NanoHTTPD as the web server. The server hosts a simple web page that can be accessed from a browser by entering the IP address of the TV.
Here’s how it works with HTTP:
- I open the browser and enter the TV’s IP address (e.g., http://192.168.1.x:8080).
- A login prompt appears (Basic/Digest Auth).
- After entering the correct credentials, the page is displayed successfully.
However, when I switch to HTTPS:
- I access the page at https://192.168.1.x:8443.
- The login prompt still appears.
- After entering correct credentials, the page remains blank — it does not load, and no content is displayed.
- There are no errors in ADB logs or browser console.
Additional Info:
Target device: Android 9-based embedded TV
Browser: Chrome/Edge (tested from a PC in the same network)
SSL: Self-signed certificate
Authentication: Basic and Digest (tested both)
No errors in ADB logcat or NanoHTTPD logs
Here is what I’ve already done:
- I’ve created a self-signed certificate using OpenSSL.
- I’ve configured NanoHTTPD to use SSL with the certificate.
- The server starts without errors and listens on the HTTPS port.
- I made sure that the MIME types and response structure are the same as HTTP.
- The credentials are accepted correctly; the problem is after authentication.
What I’d like to ask:
- Could you please look at the code snippets below and let me know if there are any mistakes or missing configurations in the HTTPS setup?
- Do I need to handle HTTPS requests differently in NanoHTTPD compared to HTTP?
- Could the problem be related to how the browser handles the self-signed certificate?
public HTTPServer(Context context, String serverPath) { super(SERVER_HOSTNAME, SERVER_PORT); this.context = context; this.serverPath = serverPath; readCredentials(); try { String ipAddress = getDeviceIpAddress(); char[] ksPassword = "password".toCharArray(); String keystoreFilePath = "/odm/etc/tvconfig/crestron/keystore.p12"; File keystoreDir = new File("/odm/etc/tvconfig/crestron/"); if (!keystoreDir.exists()) { boolean created = keystoreDir.mkdirs(); if (created) { Log.d(TAG, "Keystore created: " + keystoreDir.getAbsolutePath()); } else { Log.e(TAG, "Keystore couldn't be created: " + keystoreDir.getAbsolutePath()); } } File keystoreFile = new File(keystoreFilePath); KeyStore loadedKeyStore; if (!keystoreFile.exists() || keystoreFile.length() == 0) { Log.d(TAG, "Keystore is non-existing or blank, creating a new one..."); loadedKeyStore = createDynamicKeyStore(ipAddress, String.valueOf(ksPassword), keystoreFilePath); Log.d(TAG, "Keystore saved at '" + keystoreFilePath); } loadedKeyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream fis = new FileInputStream(keystoreFile)) { loadedKeyStore.load(fis, ksPassword); Log.d(TAG, "Keystore successfully loaded from '" + keystoreFilePath); } KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(loadedKeyStore, ksPassword); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), null, null); makeSecure(sslContext.getServerSocketFactory(), null); Log.d(TAG, "HTTPS is secured"); } catch (Exception e) { Log.e(TAG, "HTTPServer error: " + e.getMessage(), e); } generateNonce(); }// generating a generic certificate file: public KeyStore createDynamicKeyStore(String ip, String password, String filePath) throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); long now = System.currentTimeMillis(); Date startDate = new Date(now - 3600000L); Date endDate = new Date(now + 365L * 24 * 3600 * 1000); X500Name issuer = new X500Name("CN=" + ip); X500Name subject = issuer; BigInteger serial = BigInteger.valueOf(now); GeneralName ipName = new GeneralName(GeneralName.iPAddress, ip); GeneralNames subjectAltName = new GeneralNames(ipName); ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate()); X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( issuer, serial, startDate, endDate, subject, keyPair.getPublic()); certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAltName); X509Certificate certificate = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer)); KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(null, null); keyStore.setKeyEntry("dynamickey", keyPair.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{certificate}); try (FileOutputStream fos = new FileOutputStream(filePath)) { keyStore.store(fos, password.toCharArray()); Log.d(TAG, "KeyStore successfully saved at '" + filePath); } return keyStore; }