Skip to content

Commit 5da5276

Browse files
NFC-83 Unify handlePin1SmartCardReaderException and handlePin2SmartCardReaderException. Improve one left viewModelScope.launch. Fix signatureAlgorithm structure.
1 parent 6e5cb60 commit 5da5276

5 files changed

Lines changed: 120 additions & 126 deletions

File tree

app/src/main/kotlin/ee/ria/DigiDoc/viewmodel/NFCViewModel.kt

Lines changed: 50 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import android.content.pm.ActivityInfo
2727
import androidx.lifecycle.LiveData
2828
import androidx.lifecycle.MutableLiveData
2929
import androidx.lifecycle.ViewModel
30-
import androidx.lifecycle.viewModelScope
3130
import com.google.common.collect.ImmutableMap
3231
import dagger.hilt.android.lifecycle.HiltViewModel
3332
import ee.ria.DigiDoc.R
@@ -59,7 +58,6 @@ import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil.Companion.debugLog
5958
import ee.ria.DigiDoc.utilsLib.logging.LoggingUtil.Companion.errorLog
6059
import ee.ria.libdigidocpp.ExternalSigner
6160
import kotlinx.coroutines.Dispatchers.Main
62-
import kotlinx.coroutines.launch
6361
import kotlinx.coroutines.runBlocking
6462
import kotlinx.coroutines.withContext
6563
import org.bouncycastle.util.encoders.Hex
@@ -279,7 +277,7 @@ class NFCViewModel
279277
_signStatus.postValue(true)
280278
_signedContainer.postValue(container)
281279
} catch (ex: SmartCardReaderException) {
282-
handlePin2SmartCardReaderException(ex, pinType)
280+
handleSmartCardReaderException(ex, CodeType.PIN2, pinType)
283281
} catch (ex: Exception) {
284282
_signStatus.postValue(false)
285283
_shouldResetPIN.postValue(true)
@@ -367,7 +365,7 @@ class NFCViewModel
367365
_cryptoContainer.postValue(decryptedContainer)
368366
} catch (ex: SmartCardReaderException) {
369367
_decryptStatus.postValue(false)
370-
handlePin1SmartCardReaderException(ex, pinType)
368+
handleSmartCardReaderException(ex, CodeType.PIN1, pinType)
371369
} catch (ex: Exception) {
372370
_decryptStatus.postValue(false)
373371
_shouldResetPIN.postValue(true)
@@ -419,9 +417,7 @@ class NFCViewModel
419417
checkNFCStatus(
420418
nfcSmartCardReaderManager.startDiscovery(activity) { nfcReader, exc ->
421419
if ((nfcReader != null) && (exc == null)) {
422-
viewModelScope.launch {
423-
_message.postValue(R.string.signature_update_nfc_detected)
424-
}
420+
_message.postValue(R.string.signature_update_nfc_detected)
425421
try {
426422
val card = TokenWithPace.create(nfcReader)
427423
card.tunnel(canNumber)
@@ -510,7 +506,7 @@ class NFCViewModel
510506
_shouldResetPIN.postValue(true)
511507
_webEidAuthResult.postValue(Triple(authCert, signingCert, signatureArray))
512508
} catch (ex: SmartCardReaderException) {
513-
handlePin1SmartCardReaderException(ex, pinType)
509+
handleSmartCardReaderException(ex, CodeType.PIN1, pinType)
514510
} catch (ex: Exception) {
515511
_shouldResetPIN.postValue(true)
516512

@@ -637,7 +633,7 @@ class NFCViewModel
637633
Triple(signerCertB64, signatureArray, responseUri),
638634
)
639635
} catch (ex: SmartCardReaderException) {
640-
handlePin2SmartCardReaderException(ex, pinType)
636+
handleSmartCardReaderException(ex, CodeType.PIN2, pinType)
641637
} catch (ex: Exception) {
642638
_signStatus.postValue(false)
643639
_shouldResetPIN.postValue(true)
@@ -735,118 +731,59 @@ class NFCViewModel
735731
errorLog(logTag, "Unable to perform with NFC: ${e.message}", e)
736732
}
737733

738-
private fun handlePin1SmartCardReaderException(
734+
private fun handleSmartCardReaderException(
739735
ex: SmartCardReaderException,
736+
codeType: CodeType,
740737
pinType: String,
741738
) {
742-
if (ex.message?.contains("TagLostException") == true) {
743-
_errorState.postValue(Triple(R.string.signature_update_nfc_tag_lost, null, null))
744-
} else if (ex.message?.contains("PIN1 verification failed") == true &&
745-
ex.message?.contains("Retries left: 2") == true
746-
) {
747-
_shouldResetPIN.postValue(true)
748-
_errorState.postValue(
749-
Triple(
750-
R.string.id_card_sign_pin_invalid,
751-
pinType,
752-
2,
753-
),
754-
)
755-
} else if (ex.message?.contains("PIN1 verification failed") == true &&
756-
ex.message?.contains("Retries left: 1") == true
757-
) {
758-
_shouldResetPIN.postValue(true)
759-
_errorState.postValue(
760-
Triple(
761-
R.string.id_card_sign_pin_invalid_final,
762-
pinType,
763-
null,
764-
),
765-
)
766-
} else if (ex.message?.contains("PIN1 verification failed") == true &&
767-
ex.message?.contains("Retries left: 0") == true
768-
) {
769-
_shouldResetPIN.postValue(true)
770-
_errorState.postValue(
771-
Triple(
772-
R.string.id_card_sign_pin_locked,
773-
pinType,
774-
null,
775-
),
776-
)
777-
} else if (ex is ApduResponseException) {
778-
_errorState.postValue(
779-
Triple(R.string.signature_update_nfc_technical_error, null, null),
780-
)
781-
} else if (ex is PaceTunnelException) {
782-
_errorState.postValue(
783-
Triple(R.string.signature_update_nfc_wrong_can, null, null),
784-
)
785-
} else {
786-
showTechnicalError(ex)
739+
val pinName = codeType.name
740+
val isSigning = codeType == CodeType.PIN2
741+
742+
if (isSigning) {
743+
_signStatus.postValue(false)
787744
}
788745

789-
errorLog(logTag, "Exception: " + ex.message, ex)
790-
}
746+
when {
747+
ex.message?.contains("TagLostException") == true -> {
748+
_errorState.postValue(Triple(R.string.signature_update_nfc_tag_lost, null, null))
749+
}
791750

792-
private fun handlePin2SmartCardReaderException(
793-
ex: SmartCardReaderException,
794-
pinType: String,
795-
) {
796-
_signStatus.postValue(false)
797-
798-
if (ex.message?.contains("TagLostException") == true) {
799-
_errorState.postValue(
800-
Triple(
801-
R.string.signature_update_nfc_tag_lost,
802-
null,
803-
null,
804-
),
805-
)
806-
} else if (ex.message?.contains("PIN2 has not been changed") == true) {
807-
_dialogError.postValue(R.string.sign_blocked_pin2_unchanged_message)
808-
} else if (ex.message?.contains("PIN2 verification failed") == true &&
809-
ex.message?.contains("Retries left: 2") == true
810-
) {
811-
_shouldResetPIN.postValue(true)
812-
_errorState.postValue(
813-
Triple(
814-
R.string.id_card_sign_pin_invalid,
815-
pinType,
816-
2,
817-
),
818-
)
819-
} else if (ex.message?.contains("PIN2 verification failed") == true &&
820-
ex.message?.contains("Retries left: 1") == true
821-
) {
822-
_shouldResetPIN.postValue(true)
823-
_errorState.postValue(
824-
Triple(
825-
R.string.id_card_sign_pin_invalid_final,
826-
pinType,
827-
null,
828-
),
829-
)
830-
} else if (ex.message?.contains("PIN2 verification failed") == true &&
831-
ex.message?.contains("Retries left: 0") == true
832-
) {
833-
_shouldResetPIN.postValue(true)
834-
_errorState.postValue(
835-
Triple(R.string.id_card_sign_pin_locked, pinType, null),
836-
)
837-
} else if (ex is ApduResponseException) {
838-
_errorState.postValue(
839-
Triple(R.string.signature_update_nfc_technical_error, null, null),
840-
)
841-
} else if (ex is PaceTunnelException) {
842-
_errorState.postValue(
843-
Triple(R.string.signature_update_nfc_wrong_can, null, null),
844-
)
845-
} else {
846-
showTechnicalError(ex)
751+
isSigning && ex.message?.contains("PIN2 has not been changed") == true -> {
752+
_dialogError.postValue(R.string.sign_blocked_pin2_unchanged_message)
753+
}
754+
755+
ex.message?.contains("$pinName verification failed") == true &&
756+
ex.message?.contains("Retries left: 2") == true -> {
757+
_shouldResetPIN.postValue(true)
758+
_errorState.postValue(Triple(R.string.id_card_sign_pin_invalid, pinType, 2))
759+
}
760+
761+
ex.message?.contains("$pinName verification failed") == true &&
762+
ex.message?.contains("Retries left: 1") == true -> {
763+
_shouldResetPIN.postValue(true)
764+
_errorState.postValue(Triple(R.string.id_card_sign_pin_invalid_final, pinType, null))
765+
}
766+
767+
ex.message?.contains("$pinName verification failed") == true &&
768+
ex.message?.contains("Retries left: 0") == true -> {
769+
_shouldResetPIN.postValue(true)
770+
_errorState.postValue(Triple(R.string.id_card_sign_pin_locked, pinType, null))
771+
}
772+
773+
ex is ApduResponseException -> {
774+
_errorState.postValue(Triple(R.string.signature_update_nfc_technical_error, null, null))
775+
}
776+
777+
ex is PaceTunnelException -> {
778+
_errorState.postValue(Triple(R.string.signature_update_nfc_wrong_can, null, null))
779+
}
780+
781+
else -> {
782+
showTechnicalError(ex)
783+
}
847784
}
848785

849-
errorLog(logTag, "Exception: " + ex.message, ex)
786+
errorLog(logTag, "Exception: ${ex.message}", ex)
850787
}
851788

852789
private fun handleGeneralException(ex: Exception): Boolean {

web-eid-lib/src/androidTest/java/ee/ria/DigiDoc/webEid/WebEidSignServiceTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,11 @@ class WebEidSignServiceTest {
9696
val expectedSignature = Base64.getEncoder().encodeToString(signatureBytes)
9797
assertEquals(expectedSignature, result.getString("signature"))
9898

99-
val algorithm = result.getString("signatureAlgorithm")
100-
assertTrue(algorithm.startsWith("ES"))
99+
val signatureAlgorithm = result.getJSONObject("signatureAlgorithm")
100+
101+
assertEquals("ECC", signatureAlgorithm.getString("cryptoAlgorithm"))
102+
assertEquals("NONE", signatureAlgorithm.getString("paddingScheme"))
103+
assertTrue(signatureAlgorithm.getString("hashFunction").startsWith("SHA-"))
101104
}
102105

103106
@Test

web-eid-lib/src/androidTest/java/ee/ria/DigiDoc/webEid/utils/WebEidAlgorithmUtilTest.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,42 @@ class WebEidAlgorithmUtilTest {
113113
}
114114
assertTrue(exception.message!!.contains("Unsupported key type"))
115115
}
116+
117+
@Test
118+
fun buildSignatureAlgorithm_ec256_returnsCorrectAlgorithmObject() {
119+
val result =
120+
WebEidAlgorithmUtil.buildSignatureAlgorithm(ecPublicKey256)
121+
122+
assertEquals("ECC", result.getString("cryptoAlgorithm"))
123+
assertEquals("SHA-256", result.getString("hashFunction"))
124+
assertEquals("NONE", result.getString("paddingScheme"))
125+
}
126+
127+
@Test
128+
fun buildSignatureAlgorithm_ec384_returnsCorrectAlgorithmObject() {
129+
val result =
130+
WebEidAlgorithmUtil.buildSignatureAlgorithm(ecPublicKey384)
131+
132+
assertEquals("ECC", result.getString("cryptoAlgorithm"))
133+
assertEquals("SHA-384", result.getString("hashFunction"))
134+
assertEquals("NONE", result.getString("paddingScheme"))
135+
}
136+
137+
@Test
138+
fun buildSignatureAlgorithm_unsupportedKeyType_throwsException() {
139+
val rsaKey =
140+
KeyPairGenerator
141+
.getInstance("RSA")
142+
.apply {
143+
initialize(2048)
144+
}.generateKeyPair()
145+
.public
146+
147+
val exception =
148+
assertThrows(IllegalArgumentException::class.java) {
149+
WebEidAlgorithmUtil.buildSignatureAlgorithm(rsaKey)
150+
}
151+
152+
assertTrue(exception.message!!.contains("Unsupported key type"))
153+
}
116154
}

web-eid-lib/src/main/java/ee/ria/DigiDoc/webEid/WebEidSignServiceImpl.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
package ee.ria.DigiDoc.webEid
2323

24+
import ee.ria.DigiDoc.webEid.utils.WebEidAlgorithmUtil.buildSignatureAlgorithm
2425
import ee.ria.DigiDoc.webEid.utils.WebEidAlgorithmUtil.buildSupportedSignatureAlgorithms
25-
import ee.ria.DigiDoc.webEid.utils.WebEidAlgorithmUtil.getAlgorithm
2626
import org.json.JSONObject
2727
import java.security.cert.CertificateFactory
2828
import java.security.cert.X509Certificate
@@ -59,11 +59,11 @@ class WebEidSignServiceImpl
5959
.generateCertificate(certBytes.inputStream()) as X509Certificate
6060

6161
val publicKey = cert.publicKey
62-
val algorithm = getAlgorithm(publicKey)
62+
val signatureAlgorithm = buildSignatureAlgorithm(publicKey)
6363

6464
return JSONObject().apply {
6565
put("signature", Base64.getEncoder().encodeToString(signature))
66-
put("signatureAlgorithm", algorithm)
66+
put("signatureAlgorithm", signatureAlgorithm)
6767
}
6868
}
6969
}

web-eid-lib/src/main/java/ee/ria/DigiDoc/webEid/utils/WebEidAlgorithmUtil.kt

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,32 @@ object WebEidAlgorithmUtil {
5959
}
6060

6161
fun getAlgorithm(publicKey: PublicKey): String =
62-
when (publicKey) {
63-
is ECPublicKey -> {
64-
when (publicKey.params.curve.field.fieldSize) {
65-
256 -> "ES256"
66-
384 -> "ES384"
67-
521 -> "ES512"
68-
else -> throw IllegalArgumentException("Unsupported EC key length")
69-
}
62+
when (getEcKeySize(publicKey)) {
63+
256 -> "ES256"
64+
384 -> "ES384"
65+
521 -> "ES512"
66+
else -> throw IllegalArgumentException("Unsupported EC key length")
67+
}
68+
69+
fun buildSignatureAlgorithm(publicKey: PublicKey): JSONObject {
70+
val hashFunction =
71+
when (getEcKeySize(publicKey)) {
72+
256 -> "SHA-256"
73+
384 -> "SHA-384"
74+
521 -> "SHA-512"
75+
else -> throw IllegalArgumentException("Unsupported EC key length")
7076
}
7177

78+
return JSONObject().apply {
79+
put("cryptoAlgorithm", "ECC")
80+
put("hashFunction", hashFunction)
81+
put("paddingScheme", "NONE")
82+
}
83+
}
84+
85+
private fun getEcKeySize(publicKey: PublicKey): Int =
86+
when (publicKey) {
87+
is ECPublicKey -> publicKey.params.curve.field.fieldSize
7288
else -> throw IllegalArgumentException("Unsupported key type")
7389
}
7490
}

0 commit comments

Comments
 (0)