Skip to content

pagopa/iso18013-android

Repository files navigation

iso18013-android

This project is divided into two main libraries.

  1. cbor_implementation.
  2. proximity.

And one app to test these libraries.

Both libraries have one logger called ProximityLogger and CborLogger which can be used safely as in app MainActivity:

ProximityLogger.enabled = BuildConfig.DEBUG
CborLogger.enabled = BuildConfig.DEBUG

CBOR

Public classes are:

  • COSEManager
  • MDoc

COSEManager is intended to be used to sign any bytes[] using COSE and also verify COSE signature.
Examples:
Sign data:

val data = //your byte array data
when (val result = coseManager.signWithCOSE(
    data = data,
    alias = "pagoPA"
)) {
    is SignWithCOSEResult.Failure -> failureAppDialog(result.msg)
    is SignWithCOSEResult.Success -> {
        // handle result
        signature = result.signature//bytes[]
        publicKey = result.publicKey//bytes[]
    }
}

Verify Sign1Message:

// it returns a Boolean
coseManager.verifySign1(
    dataSigned = what,
    publicKey = pubKey
)

In app you can find these examples into SignAndVerifyViewViewModel class.
MDoc:

The MDoc class is a polymorphic class in Kotlin that returns an object of type ModelMDoc. The ModelMDoc is a parser for a CBOR format, which includes a method to convert it to JSON. The MDoc class has three constructors:

  1. Primary Constructor: This is private and is used internally by the other constructors.

    private constructor(source: Any, isByteArray: Boolean = false)
  2. String Constructor: This takes a Base64String source and sets isByteArray to false.

    constructor(source: String) : this(source, false)
  3. ByteArray Constructor: This takes a bytes[] source and sets isByteArray to true.

    constructor(source: ByteArray) : this(source, true)

Proximity

Public classes are:

  • QrEngagement
  • ResponseGenerator

and a data class:

/**
 * BLE Retrieval Method
 * @property peripheralServerMode set if the peripheral server mode is enabled
 * @property centralClientMode set if the central client mode is enabled
 * @property clearBleCache set if the BLE cache should be cleared
 */
data class BleRetrievalMethod(
    val peripheralServerMode: Boolean,
    val centralClientMode: Boolean,
    val clearBleCache: Boolean
) : DeviceRetrievalMethod

QrEngagement:

companion object {
        /**
         * Create an instance and configures the QR engagement.
         * First of all you must call [configure] to build QrEngagementHelper.
         * To accept just some certificates use [withReaderTrustStore] method.
         * To create a QrCode use [getQrCodeString] method.
         * To observe all events call [withListener] method.
         * To close the connection call [close] method.
         */
        fun build(context: Context, retrievalMethods: List<DeviceRetrievalMethod>): QrEngagement {
            return QrEngagement(context).apply {
                this.retrievalMethods = retrievalMethods
                qrEngagementBuilder = QrEngagementHelper.Builder(
                    context,
                    eDevicePrivateKey.publicKey,
                    retrievalMethods.transportOptions,
                    qrEngagementListener,
                    context.mainExecutor()
                ).setConnectionMethods(retrievalMethods.connectionMethods)
            }
        }
    }

This is thew way this class is intended to be instantiated. Examples can be found into MasterViewViewModel class.

Methods:

  1. configure: builds QrEngagementHelper by com.android.identity package and returns QrEngagement instance created via QrEngagement.build static method.

    fun configure() = apply {
       qrEngagement = qrEngagementBuilder.build()
    }
  2. withReaderTrustStore: Method to inject certificates to be verified sent by mdoc verifier app.

    /**
    * Use this if you have certificates into your **Raw Resource** folder.
    * *You have still other two methods with [List] of [ByteArray] for raw certificates and [List] of [String] for pem*
    * @param certificates a [List] of [Int] representing your raw resource
    * @return [QrEngagement]
      */
      fun withReaderTrustStore(certificates: List<Int>) = apply {
         certificates.setReaderTrustStore()
      }
    
    /**
    * Use this if you have certificates **As [ByteArray]**.
    * *You have still other two methods with [List] of [Int] for raw resources and [List] of [String] for pem*
    * @param certificates a [List] of [ByteArray] representing your raw certificates
    * @return [QrEngagement]
      */
      @JvmName("withReaderTrustStore1")
      fun withReaderTrustStore(certificates: List<ByteArray>) = apply {
         certificates.setReaderTrustStore()
      }
    
    /**
    * Use this if you have certificates **As [String]**.
    * *You have still other two methods with [List] of [Int] for raw resources and [List] of [ByteArray] for raw certificates*
    * @param certificates a [List] of [String] representing your pem certificates
    * @return [QrEngagement]
      */
      @JvmName("withReaderTrustStore2")
      fun withReaderTrustStore(certificates: List<String>) = apply {
         certificates.setReaderTrustStore()
      }
  3. getQrCodeString: Gives back QR code string for engagement

    fun getQrCodeString() = apply {
       if (!checkQrEngagementInit())
          return ""
      return qrEngagement.deviceEngagementUriEncoded
    }
  4. withListener: Starts the listener for qrCodeEngagement

    fun withListener(callback: QrEngagementListener) = apply {
      this.listener = callback
    }
  5. close: Closes the connection with the mdoc verifier

    fun close() {
      if (!checkQrEngagementInit())
          return
      try {
          if (deviceRetrievalHelper != null)
              deviceRetrievalHelper!!.disconnect()
          qrEngagement.close()
      } catch (exception: RuntimeException) {
          ProximityLogger.e(this.javaClass.name, "Error closing QR engagement $exception")
      }
    }

The listener:

interface QrEngagementListener {
    fun onConnecting()
    fun onDeviceRetrievalHelperReady(deviceRetrievalHelper: DeviceRetrievalHelperWrapper)
    fun onCommunicationError(msg: String)
    fun onNewDeviceRequest(request: String?, sessionsTranscript: ByteArray)
    fun onDeviceDisconnected(transportSpecificTermination: Boolean)
}

ResponseGenerator:

interface Response {
     /**@param [response] [ByteArray] generated for response*/
     fun onResponseGenerated(response: ByteArray)

     /**@param [message] [String] for error reached*/
     fun onError(message: String)
 }

 /**
  * It creates a mdoc response in ByteArray format respect documents requested and disclosed
  * @return[Response.onResponseGenerated] if ByteArray is created without Exceptions, else
  * [Response.onError] if disclosedDocumentsArray is Empty with "no doc found" message or if an
  * [Exception] was reached with [Throwable.message].
  */
 @JvmName("createResponseWithCallback")
 fun createResponse(
     documents: Array<DocRequested>,
     fieldRequestedAndAccepted: String,
     response: Response
 ) {
     val (responseToSend, message) = this.createResponse(
         documents, fieldRequestedAndAccepted
     )
     responseToSend?.let {
         response.onResponseGenerated(it)
     } ?: run {
         response.onError(message)
         ProximityLogger.e(
             "Sending resp",
             "found doc but fail to generate raw response: $message"
         )
     }
 }

where DocRequested is:

@Parcelize
data class DocRequested(
    val content: String,
    val alias: String
) : Parcelable

See in app MasterViewViewModel.shareInfo method to understand how to retrieve documents from JSON request and correctly send to response.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 3

  •  
  •  
  •  

Languages