Certificate pinning for websockets in android

925 views Asked by At

We are using websockets in one of my Android app. Using 3rd party lib "https://github.com/TakahikoKawasaki/nv-websocket-client" .

Now we wanted to enable ssl pinning for websockets. How can we do this?

Thanks

1

There are 1 answers

0
user3863488 On
We can enable ssl pinning for web sockets using sslContext. 

This is my working code.



----------
val sslContext =  SSLContext.getInstance("TLS")
        sslContext.init(null, arrayOf(CustomTrustManager(null)), SecureRandom())
        mSocketFactory.sslContext = sslContext
        val ws = mSocketFactory.createSocket(presentEndpoint)



class CustomTrustManager(keyStore: KeyStore?) : X509TrustManager {

    private val tag = CustomTrustManager::class.java.canonicalName

    init {
        val factory: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
        factory.init(keyStore)
        val trustmanagers: Array<TrustManager> = factory.trustManagers
        if (trustmanagers.isEmpty()) {
            throw NoSuchAlgorithmException("no trust manager found")
        }
    }

    override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {

    }

    override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        for (certificate in chain!!) {
            if (isValidPin(certificate)) {
                return
            }
        }
        throw  CertificateException("No valid pins found in chain!")
    }

    override fun getAcceptedIssuers(): Array<X509Certificate>? {

        return null
    }

    private fun isValidPin(certificate: X509Certificate): Boolean {
        return try {
            val md = MessageDigest.getInstance("SHA-256")
            val publicKey = certificate.publicKey.encoded
            md.update(publicKey, 0, publicKey.size)
            val pin = Base64.encodeToString(md.digest(), Base64.NO_WRAP)
            val validPins = Collections.singleton(Constants.PK)
            if (validPins.contains("sha256/$pin")) {
                return true
            }
            false
        } catch (ex: NoSuchAlgorithmException) {
            throw CertificateException(ex)
        }
    }

}