-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update CredentialPack to use ParsedCredential (#39)
* Update CredentialPack to use ParsedCredential * Update SpruceKit Demo * Small adjustments to make demo app compatible * Parse any JSON type --------- Co-authored-by: Juliano Cezar Chagas Tavares <[email protected]>
- Loading branch information
1 parent
99ad02e
commit 6b039d4
Showing
12 changed files
with
309 additions
and
236 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
33 changes: 0 additions & 33 deletions
33
MobileSdk/src/main/java/com/spruceid/mobile/sdk/BaseCredential.kt
This file was deleted.
Oops, something went wrong.
112 changes: 112 additions & 0 deletions
112
MobileSdk/src/main/java/com/spruceid/mobile/sdk/Credential.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package com.spruceid.mobile.sdk | ||
|
||
import com.spruceid.mobile.sdk.rs.JsonVc | ||
import com.spruceid.mobile.sdk.rs.JwtVc | ||
import com.spruceid.mobile.sdk.rs.Mdoc | ||
import org.json.JSONException | ||
import org.json.JSONObject | ||
import org.json.JSONTokener | ||
|
||
/** | ||
* Access all of the elements in the mdoc, ignoring namespaces and missing elements that cannot be encoded as JSON. | ||
*/ | ||
fun Mdoc.jsonEncodedDetailsAll(): JSONObject = this.jsonEncodedDetailsInternal(null) | ||
|
||
/** | ||
* Access the specified elements in the mdoc, ignoring namespaces and missing elements that cannot be encoded as JSON. | ||
*/ | ||
fun Mdoc.jsonEncodedDetailsFiltered(elementIdentifiers: List<String>): JSONObject = this.jsonEncodedDetailsInternal(elementIdentifiers) | ||
|
||
|
||
private fun Mdoc.jsonEncodedDetailsInternal(elementIdentifiers: List<String>?): JSONObject = | ||
JSONObject( | ||
// Ignore the namespaces. | ||
this.details().values.flatMap { elements -> | ||
elements.map { element -> | ||
val id = element.identifier | ||
val jsonString = element.value | ||
|
||
// If a filter is provided, filter out non-specified ids. | ||
if (elementIdentifiers != null) { | ||
if (!elementIdentifiers.contains(id)) { | ||
return@map null | ||
} | ||
} | ||
|
||
if (jsonString != null) { | ||
try { | ||
val jsonElement = JSONTokener(jsonString).nextValue() | ||
return@map Pair(id, jsonElement) | ||
} catch (e: JSONException) { | ||
print("failed to decode '$id' as JSON: $e") | ||
} | ||
} | ||
|
||
return@map null | ||
} | ||
}.filterNotNull().toMap() | ||
) | ||
|
||
/** | ||
* Access the W3C VCDM credential (not including the JWT envelope). | ||
*/ | ||
fun JwtVc.credentialClaims(): JSONObject { | ||
try { | ||
return JSONObject(this.credentialAsJsonEncodedUtf8String()) | ||
} catch (e: Error) { | ||
print("failed to decode VCDM data from UTF-8-encoded JSON") | ||
return JSONObject() | ||
} | ||
} | ||
|
||
/** | ||
* Access the specified claims from the W3C VCDM credential (not including the JWT envelope). | ||
*/ | ||
fun JwtVc.credentialClaimsFiltered(claimNames: List<String>): JSONObject { | ||
val old = this.credentialClaims() | ||
val new = JSONObject() | ||
for (name in claimNames) { | ||
if (old.has(name)) { | ||
new.put(name, keyPathFinder(old, name.split(".").toMutableList())) | ||
} | ||
} | ||
return new | ||
} | ||
|
||
/** | ||
* Access the W3C VCDM credential. | ||
*/ | ||
fun JsonVc.credentialClaims(): JSONObject { | ||
try { | ||
return JSONObject(this.credentialAsJsonEncodedUtf8String()) | ||
} catch (e: Error) { | ||
print("failed to decode VCDM data from UTF-8-encoded JSON") | ||
return JSONObject() | ||
} | ||
} | ||
|
||
/** | ||
* Access the specified claims from the W3C VCDM credential. | ||
*/ | ||
fun JsonVc.credentialClaimsFiltered(claimNames: List<String>): JSONObject { | ||
val old = this.credentialClaims() | ||
val new = JSONObject() | ||
for (name in claimNames) { | ||
new.put(name, keyPathFinder(old, name.split(".").toMutableList())) | ||
} | ||
return new | ||
} | ||
|
||
private fun keyPathFinder(json: Any, path: MutableList<String>): Any { | ||
try { | ||
val firstKey = path.first() | ||
val element = (json as JSONObject)[firstKey] | ||
path.removeAt(0) | ||
if (path.isNotEmpty()) { | ||
return keyPathFinder(element, path) | ||
} | ||
return element | ||
} catch (e: Exception) { | ||
return "" | ||
} | ||
} |
156 changes: 73 additions & 83 deletions
156
MobileSdk/src/main/java/com/spruceid/mobile/sdk/CredentialPack.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,98 @@ | ||
package com.spruceid.mobile.sdk | ||
|
||
import java.security.KeyFactory | ||
import java.security.KeyStore | ||
import java.security.cert.Certificate | ||
import java.security.cert.CertificateFactory | ||
import java.security.spec.PKCS8EncodedKeySpec | ||
import java.util.Base64 | ||
import com.spruceid.mobile.sdk.rs.JsonVc | ||
import com.spruceid.mobile.sdk.rs.JwtVc | ||
import com.spruceid.mobile.sdk.rs.Mdoc | ||
import com.spruceid.mobile.sdk.rs.ParsedCredential | ||
import org.json.JSONObject | ||
|
||
/** | ||
* Collection of BaseCredentials with methods to interact with all instances | ||
*/ | ||
class CredentialPack { | ||
private val credentials: MutableList<BaseCredential> | ||
private val credentials: MutableList<ParsedCredential> | ||
|
||
constructor() { | ||
credentials = mutableListOf() | ||
} | ||
|
||
constructor(credentialsArray: MutableList<BaseCredential>) { | ||
constructor(credentialsArray: MutableList<ParsedCredential>) { | ||
this.credentials = credentialsArray | ||
} | ||
|
||
fun addW3CVC(credentialString: String): List<BaseCredential> { | ||
val vc = W3CVC(credentialString = credentialString) | ||
credentials.add(vc) | ||
/** | ||
* Add a JwtVc to the CredentialPack. | ||
*/ | ||
fun addJwtVc(jwtVc: JwtVc): List<ParsedCredential> { | ||
credentials.add(ParsedCredential.newJwtVcJson(jwtVc)) | ||
return credentials | ||
} | ||
|
||
fun addMDoc( | ||
id: String, | ||
mdocBase64: String, | ||
keyPEM: String, | ||
keyBase64: String | ||
): List<BaseCredential> { | ||
try { | ||
val decodedKey = Base64.getDecoder().decode( | ||
keyBase64 | ||
) | ||
|
||
val privateKey = KeyFactory.getInstance( | ||
"EC" | ||
).generatePrivate( | ||
PKCS8EncodedKeySpec( | ||
decodedKey | ||
) | ||
) | ||
|
||
val cert: Array<Certificate> = arrayOf( | ||
CertificateFactory.getInstance( | ||
"X.509" | ||
).generateCertificate( | ||
keyPEM.byteInputStream() | ||
) | ||
) | ||
|
||
val ks: KeyStore = KeyStore.getInstance( | ||
"AndroidKeyStore" | ||
) | ||
|
||
ks.load( | ||
null | ||
) | ||
|
||
ks.setKeyEntry( | ||
"someAlias", | ||
privateKey, | ||
null, | ||
cert | ||
) | ||
|
||
credentials.add( | ||
MDoc( | ||
id, | ||
Base64.getDecoder().decode(mdocBase64), | ||
"someAlias" | ||
) | ||
) | ||
} catch (e: Throwable) { | ||
print( | ||
e | ||
) | ||
throw e | ||
} | ||
/** | ||
* Add a JsonVc to the CredentialPack. | ||
*/ | ||
fun addJsonVc(jsonVc: JsonVc): List<ParsedCredential> { | ||
credentials.add(ParsedCredential.newLdpVc(jsonVc)) | ||
return credentials | ||
} | ||
|
||
fun get(keys: List<String>): Map<String, Map<String, Any>> { | ||
val values = emptyMap<String, Map<String, Any>>().toMutableMap() | ||
|
||
for (credential in credentials) { | ||
values[credential.getId()!!] = credential.get(keys) | ||
} | ||
return values | ||
} | ||
|
||
fun getCredentialsByIds(credentialsIds: List<String>): List<BaseCredential> { | ||
return credentials.filter { credential -> credentialsIds.contains(credential.getId()) } | ||
} | ||
|
||
fun getCredentials(): List<BaseCredential> { | ||
/** | ||
* Add an Mdoc to the CredentialPack. | ||
*/ | ||
fun addMdoc(mdoc: Mdoc): List<ParsedCredential> { | ||
credentials.add(ParsedCredential.newMsoMdoc(mdoc)) | ||
return credentials | ||
} | ||
|
||
fun getCredentialById(credentialId: String): BaseCredential? { | ||
return credentials.find { credential -> credential.getId().equals(credentialId) } | ||
} | ||
/** | ||
* Find claims from all credentials in this CredentialPack. | ||
*/ | ||
fun findCredentialClaims(claimNames: List<String>): Map<String, JSONObject> = | ||
this.list() | ||
.map { credential -> | ||
var claims: JSONObject | ||
val mdoc = credential.asMsoMdoc() | ||
val jwtVc = credential.asJwtVc() | ||
val jsonVc = credential.asJsonVc() | ||
|
||
if (mdoc != null) { | ||
claims = mdoc.jsonEncodedDetailsFiltered(claimNames) | ||
} else if (jwtVc != null) { | ||
claims = jwtVc.credentialClaimsFiltered(claimNames) | ||
} else if (jsonVc != null) { | ||
claims = jsonVc.credentialClaimsFiltered(claimNames) | ||
} else { | ||
var type: String | ||
try { | ||
type = credential.intoGenericForm().type | ||
} catch (e: Error) { | ||
type = "unknown" | ||
} | ||
print("unsupported credential type: $type") | ||
claims = JSONObject() | ||
} | ||
|
||
return@map Pair(credential.id(), claims) | ||
} | ||
.toMap() | ||
|
||
|
||
/** | ||
* Get credentials by id. | ||
*/ | ||
fun getCredentialsByIds(credentialsIds: List<String>): List<ParsedCredential> = | ||
this.list().filter { credential -> credentialsIds.contains(credential.id()) } | ||
|
||
|
||
/** | ||
* Get a credential by id. | ||
*/ | ||
fun getCredentialById(credentialId: String): ParsedCredential? = | ||
this.list().find { credential -> credential.id() == credentialId } | ||
|
||
|
||
/** | ||
* List all of the credentials in the CredentialPack. | ||
*/ | ||
fun list(): List<ParsedCredential> = this.credentials | ||
} |
Oops, something went wrong.