add certificate pinning support for Android
This commit is contained in:
parent
8baac45187
commit
b0cb2b8933
@ -4,9 +4,6 @@
|
||||
>
|
||||
> This repository contains a proof-of-concept React Native plugin and an example mobile application intended solely for technical evaluation.
|
||||
>
|
||||
> Only the iOS integration has been verified to work at this time.
|
||||
> The Android bridge and Android example setup exist but have not been tested and are expected to require additional adjustments before they can be considered functional.
|
||||
>
|
||||
> This repository is **experimental**, **not formally approved**, **not officially released**, **not published as an npm package**, and **not endorsed by WebID for
|
||||
> production use**.
|
||||
>
|
||||
@ -38,12 +35,14 @@ cp .env.example .env
|
||||
URL=https://test.webid-solutions.de
|
||||
USERNAME=your_username
|
||||
API_KEY=your_api_key
|
||||
CERT_BASE64=On ANdroid it need to be SHA-PINS
|
||||
# SHA_PINS=sha256/AAAA...,sha256/BBBB...
|
||||
CERT_BASE64=
|
||||
```
|
||||
|
||||
Edit the .env file and add your username and API key.
|
||||
|
||||
ℹ️ The provided CERT_BASE64 value is preconfigured for the test system and is valid until 2026-02-21.
|
||||
In most cases, this value does not need to be modified if you intend to test against the test environment.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
From the repository root:
|
||||
|
||||
@ -24,6 +24,11 @@ import java.net.URI
|
||||
import com.facebook.react.bridge.UiThreadUtil
|
||||
import android.util.Log
|
||||
import com.google.gson.Gson
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.security.MessageDigest
|
||||
import java.security.cert.CertificateFactory
|
||||
import java.security.cert.X509Certificate
|
||||
import android.util.Base64
|
||||
|
||||
private const val TAG = "WebIdMetaPlugin"
|
||||
|
||||
@ -53,6 +58,53 @@ class WebIdMetaPluginModule(
|
||||
listenerCount = (listenerCount - count).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
private fun toPinningShaKey(inputRaw: String): String {
|
||||
val input = inputRaw.trim()
|
||||
|
||||
if (input.startsWith("sha256/") || input.startsWith("sha1/")) return input
|
||||
|
||||
val justValue = input.substringAfter("=", input).trim()
|
||||
|
||||
val base64Cert = justValue
|
||||
.replace("-----BEGIN CERTIFICATE-----", "")
|
||||
.replace("-----END CERTIFICATE-----", "")
|
||||
.replace("\\s+".toRegex(), "")
|
||||
|
||||
require(base64Cert.isNotEmpty()) { "Certificate input is empty after normalization" }
|
||||
|
||||
val certBytes = try {
|
||||
Base64.decode(base64Cert, Base64.DEFAULT)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw IllegalArgumentException("Certificate is not valid Base64 (DER/PEM).", e)
|
||||
}
|
||||
|
||||
val x509 = try {
|
||||
val cf = CertificateFactory.getInstance("X.509")
|
||||
cf.generateCertificate(ByteArrayInputStream(certBytes)) as X509Certificate
|
||||
} catch (e: Exception) {
|
||||
throw IllegalArgumentException("Could not parse X.509 certificate bytes.", e)
|
||||
}
|
||||
|
||||
val spkiBytes = x509.publicKey.encoded
|
||||
val digest = MessageDigest.getInstance("SHA-256").digest(spkiBytes)
|
||||
val pinB64 = Base64.encodeToString(digest, Base64.NO_WRAP)
|
||||
|
||||
return "sha256/$pinB64"
|
||||
}
|
||||
|
||||
private fun toPinningShaKeys(inputs: List<String>): Array<String> =
|
||||
inputs
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotEmpty() }
|
||||
.map { toPinningShaKey(it) }
|
||||
.toTypedArray()
|
||||
|
||||
private fun shortPreview(s: String): String {
|
||||
val t = s.trim()
|
||||
if (t.length <= 12) return t
|
||||
return "${t.take(6)}...${t.takeLast(6)}"
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun createMetaPlugin(
|
||||
uri: String,
|
||||
@ -69,10 +121,13 @@ class WebIdMetaPluginModule(
|
||||
val shaPinsList = shaPins.toArrayList().map { it.toString() }
|
||||
val pluginsList = plugins.toArrayList().map { it.toString() }
|
||||
|
||||
val pinningShaKeys = toPinningShaKeys(shaPinsList)
|
||||
Log.i(TAG, "createMetaPlugin pins(mapped) len=${pinningShaKeys.size} values=${pinningShaKeys.map { shortPreview(it) }}")
|
||||
|
||||
try {
|
||||
val environment = WebIdSdkEnvironment(
|
||||
URI.create(cleanUri),
|
||||
*shaPinsList.toTypedArray()
|
||||
*pinningShaKeys
|
||||
)
|
||||
|
||||
val selectedPlugins = ArrayList<IProductPluginWebId>()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user