Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
196a07b
remove softauthn
mariobodemann Sep 11, 2025
60b0617
polish: cleanup and align containers
mariobodemann Sep 11, 2025
2efbcd0
polish: align yubico container naming
mariobodemann Sep 11, 2025
446dbdf
add local base credential creation
mariobodemann Sep 12, 2025
732883b
local container: add creation and assertation
mariobodemann Sep 17, 2025
056b525
fix: empty instance url is ok
mariobodemann Sep 17, 2025
bb4b472
fix: move utility function to own file
mariobodemann Sep 17, 2025
58c8c76
add multiple algorithms
mariobodemann Sep 18, 2025
b006a1b
fix: crash on unwrapping
mariobodemann Sep 19, 2025
f7ade44
Revert "add wildcard intent filters"
mariobodemann Sep 19, 2025
adb1cca
use COSE-JAVA
mariobodemann Sep 23, 2025
d09bc0a
fix: create credentials return correcte response
mariobodemann Sep 29, 2025
2348b24
echo yolomessages to log
mariobodemann Sep 29, 2025
3b7b845
remove yubikey from passkeyprovider
mariobodemann Sep 30, 2025
c4e8763
typo fix in filename
mariobodemann Oct 2, 2025
0c5b713
initial create and get credential with meta storage
mariobodemann Oct 2, 2025
4c82086
simplify function for determine if we are called from withing the www…
mariobodemann Oct 2, 2025
571a130
simpify local container handling
mariobodemann Oct 2, 2025
d276b77
polish ui for passkey creation and getting
mariobodemann Oct 2, 2025
d382b47
increment request id with every request for pending intents
mariobodemann Oct 3, 2025
ebabffe
update origins and rpids
mariobodemann Oct 3, 2025
eb36ba1
remove unneded function
mariobodemann Oct 3, 2025
a33a4b3
Kicking jsonobject for adding random escape characters
mariobodemann Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ kotlin.code.style=official
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

wallet.versionCode = 17
wallet.versionName = 0.0.17=multi-profile-preview
wallet.versionCode = 19
wallet.versionName = 0.0.17-platform-passkey-provider-preview

8 changes: 5 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ logback = "3.0.0"
test-json = "20231013"
coroutines = "1.10.1"
androidxtest = "1.6.1"
softauth = "fix~rp-origin-SNAPSHOT"
ktlint = "12.2.0"
gps-ic = "16.0.0-alpha06"
registryDigitalcredentialsMdoc = "1.0.0-alpha01"
datastore = "1.1.7"
cbor = "4.5.6"
cose = "1.1.0"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
Expand Down Expand Up @@ -48,12 +49,13 @@ logback = { group = "com.github.tony19", name = "logback-android", version.ref =
test-json = { group = "org.json", name = "json", version.ref = "test-json" }
androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxtest" }
androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxtest" }
softauth = { group = "com.github.yubicolabs", name = "softauthn", version.ref = "softauth" }
playservices-identity-credentials = { group = "com.google.android.gms", name = "play-services-identity-credentials", version.ref = "gps-ic" }
androidx-registry-digitalcredentials-mdoc = { group = "androidx.credentials.registry", name = "registry-digitalcredentials-mdoc", version.ref = "registryDigitalcredentialsMdoc" }
androidx-registry-provider = { group = "androidx.credentials.registry", name = "registry-provider", version.ref = "registryDigitalcredentialsMdoc" }
androidx-registry-provider-play-services = { group = "androidx.credentials.registry", name = "registry-provider-play-services", version.ref = "registryDigitalcredentialsMdoc" }
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore"}
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" }
cbor = { group = "com.upokecenter", name = "cbor", version.ref = "cbor" }
cose = { group = "com.augustcellars.cose", name = "cose-java", version.ref = "cose" }

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
Expand Down
3 changes: 2 additions & 1 deletion wrapper/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ dependencies {
implementation(libs.yubikit.fido)
implementation(libs.logback)
implementation(libs.androidx.datastore.preferences)
implementation(libs.cbor)
implementation(libs.cose)

// digital credentials api
implementation(libs.playservices.identity.credentials)
implementation(libs.androidx.registry.provider)
implementation(libs.androidx.registry.provider.play.services)
implementation(libs.androidx.registry.digitalcredentials.mdoc)
implementation(libs.softauth)

testImplementation(libs.junit)
testImplementation(libs.test.json)
Expand Down
23 changes: 21 additions & 2 deletions wrapper/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,26 @@

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="*.wwwallet.org" />
<data android:host="funke.wwwallet.org" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="openid4vp" />
<data android:host="funke.wwwallet.org" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="demo.wwwallet.org" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
Expand All @@ -89,7 +108,7 @@
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="openid4vp" />
<data android:host="*.wwwallet.org" />
<data android:host="demo.wwwallet.org" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
Expand Down
6 changes: 2 additions & 4 deletions wrapper/src/main/java/io/yubicolabs/wwwwallet/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ import io.yubicolabs.wwwwallet.bridging.DebugMenuHandler
import io.yubicolabs.wwwwallet.bridging.WalletJsBridge
import io.yubicolabs.wwwwallet.bridging.WalletJsBridge.Companion.JAVASCRIPT_BRIDGE_NAME
import io.yubicolabs.wwwwallet.credentials.AndroidContainer
import io.yubicolabs.wwwwallet.credentials.ContainerYubico
import io.yubicolabs.wwwwallet.credentials.SoftwareContainer
import io.yubicolabs.wwwwallet.credentials.YubicoContainer
import io.yubicolabs.wwwwallet.logging.YOLOLogger
import io.yubicolabs.wwwwallet.webkit.WalletWebChromeClient
import io.yubicolabs.wwwwallet.webkit.WalletWebViewClient
Expand Down Expand Up @@ -77,9 +76,8 @@ class MainActivity : ComponentActivity() {
WalletJsBridge(
webView,
Dispatchers.Main,
ContainerYubico(activity = this),
YubicoContainer(activity = this),
AndroidContainer(context = this),
SoftwareContainer(applicationContext),
BleClientHandler(activity = this),
BleServerHandler(activity = this),
if (BuildConfig.DEBUG) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class MainViewModel : ViewModel() {
when {
value.startsWith("https://") -> value
value.startsWith("http://") -> value.replace("http", "https")
value.first().isLetter() -> "https://$value" // forgot the https?
value.isNotEmpty() && value.first().isLetter() -> "https://$value" // forgot the https?
else -> value // for direct ip addresses
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class WalletJsBridge(
private val dispatcher: CoroutineDispatcher,
private val securityKeyCredentialsContainer: Container,
private val clientDeviceCredentialsContainer: Container,
private val emulatedCredentialsContainer: Container,
private val bleClientHandler: BleClientHandler,
private val bleServerHandler: BleServerHandler,
private val debugMenuHandler: DebugMenuHandler?,
Expand All @@ -47,8 +46,6 @@ class WalletJsBridge(
"security-key" -> securityKeyCredentialsContainer
"client-device" -> clientDeviceCredentialsContainer
"hybrid" -> null // explicitly not supported
// not in spec: added for testing
"emulator" -> emulatedCredentialsContainer
else -> {
// error case: unknown hint.
YOLOLogger.e(tagForLog, "Hint '$hint' not supported. Ignoring.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.yubicolabs.wwwwallet.credentials;

import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;


/**
* Implements HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc5869">rfc5869</a>
* @see <a href="https://github.com/yubico/yubikit-android/blob/main/fido/src/main/java/com/yubico/yubikit/fido/ctap/Hkdf.java">initial source</a>
*/
class HKDF {

private final Mac mac;

public HKDF(String algo) throws NoSuchAlgorithmException {
this.mac = Mac.getInstance(algo);
}

byte[] hmacDigest(byte[] key, byte[] data) throws InvalidKeyException {
mac.init(new SecretKeySpec(key, mac.getAlgorithm()));
return mac.doFinal(data);
}

byte[] extract(byte[] salt, byte[] ikm) throws InvalidKeyException {
return hmacDigest(salt.length != 0 ? salt : new byte[mac.getMacLength()], ikm);
}

byte[] expand(byte[] prk, byte[] info, int length) throws InvalidKeyException {
byte[] t = new byte[0];
byte[] okm = new byte[0];
byte i = 0;
while (okm.length < length) {
i++;
byte[] data = ByteBuffer.allocate(t.length + info.length + 1).put(t).put(info).put(i).array();
Arrays.fill(t, (byte) 0);
byte[] digest = hmacDigest(prk, data);

byte[] result = ByteBuffer.allocate(okm.length + digest.length).put(okm).put(digest).array();
Arrays.fill(okm, (byte) 0);
Arrays.fill(data, (byte) 0);
okm = result;
t = digest;
}

byte[] result = Arrays.copyOf(okm, length);
Arrays.fill(okm, (byte) 0);
return result;
}

byte[] digest(byte[] ikm, byte[] salt, byte[] info, int length) throws InvalidKeyException {
byte[] prk = extract(salt, ikm);
byte[] result = expand(prk, info, length);
Arrays.fill(prk, (byte) 0);
return result;
}
}
Loading