mirror of
https://github.com/TanelOrumaa/Estonian-ID-card-mobile-authenticator-POC.git
synced 2025-08-30 07:10:59 +03:00
Compare commits
7 Commits
iteration4
...
MOB-24-use
Author | SHA1 | Date | |
---|---|---|---|
|
1c7e51d69a | ||
|
b623dadff5 | ||
|
4fcdccfb5e | ||
|
70991ae682 | ||
|
dbc758fb14 | ||
|
1037d672d5 | ||
|
73efb00368 |
@@ -4,7 +4,6 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.nfc.NfcAdapter
|
import android.nfc.NfcAdapter
|
||||||
import android.nfc.TagLostException
|
|
||||||
import android.nfc.tech.IsoDep
|
import android.nfc.tech.IsoDep
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.CountDownTimer
|
import android.os.CountDownTimer
|
||||||
@@ -18,11 +17,16 @@ import androidx.fragment.app.activityViewModels
|
|||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.tarkvaraprojekt.mobileauthapp.NFC.Comms
|
import com.tarkvaraprojekt.mobileauthapp.NFC.Comms
|
||||||
|
import com.tarkvaraprojekt.mobileauthapp.auth.AuthAppException
|
||||||
import com.tarkvaraprojekt.mobileauthapp.auth.Authenticator
|
import com.tarkvaraprojekt.mobileauthapp.auth.Authenticator
|
||||||
|
import com.tarkvaraprojekt.mobileauthapp.auth.InvalidCANException
|
||||||
|
import com.tarkvaraprojekt.mobileauthapp.auth.InvalidPINException
|
||||||
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentAuthBinding
|
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentAuthBinding
|
||||||
import com.tarkvaraprojekt.mobileauthapp.model.ParametersViewModel
|
import com.tarkvaraprojekt.mobileauthapp.model.ParametersViewModel
|
||||||
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
|
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
|
||||||
|
import java.io.IOException
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
import java.security.GeneralSecurityException
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,6 +111,9 @@ class AuthFragment : Fragment() {
|
|||||||
requireActivity().runOnUiThread {
|
requireActivity().runOnUiThread {
|
||||||
binding.timeCounter.text = getString(R.string.card_detected)
|
binding.timeCounter.text = getString(R.string.card_detected)
|
||||||
}
|
}
|
||||||
|
var msgCode = 0
|
||||||
|
var msgArg : Int? = null
|
||||||
|
|
||||||
val card = IsoDep.get(tag)
|
val card = IsoDep.get(tag)
|
||||||
card.timeout = 32768
|
card.timeout = 32768
|
||||||
card.use {
|
card.use {
|
||||||
@@ -119,31 +126,49 @@ class AuthFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
paramsModel.setToken(jws)
|
paramsModel.setToken(jws)
|
||||||
requireActivity().runOnUiThread {
|
requireActivity().runOnUiThread {
|
||||||
|
binding.timeCounter.text = getString(R.string.data_read)
|
||||||
goToNextFragment()
|
goToNextFragment()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: android.nfc.TagLostException) {
|
||||||
when(e) {
|
msgCode = R.string.tag_lost
|
||||||
is TagLostException -> requireActivity().runOnUiThread { binding!!.timeCounter.text = getString(R.string.id_card_removed_early) }
|
} catch (e: InvalidCANException) {
|
||||||
else -> {
|
msgCode = R.string.wrong_can_text
|
||||||
when ("invalid pin") {
|
// If the CAN is wrong we will also delete the saved CAN so that the user won't use it again.
|
||||||
in e.message.toString().lowercase() -> requireActivity().runOnUiThread {
|
viewModel.deleteCan(requireContext())
|
||||||
val messagePieces = e.message.toString().split(" ")
|
} catch (e: InvalidPINException) {
|
||||||
binding.timeCounter.text = getString(R.string.wrong_pin, messagePieces[messagePieces.size - 1])
|
msgCode = R.string.wrong_pin
|
||||||
viewModel.deletePin(requireContext())
|
msgArg = e.remainingAttempts
|
||||||
}
|
viewModel.deletePin(requireContext())
|
||||||
else -> requireActivity().runOnUiThread {
|
} catch (e: AuthAppException) {
|
||||||
binding.timeCounter.text = getString(R.string.wrong_can_text)
|
msgCode = when (e.code) {
|
||||||
viewModel.deleteCan(requireContext())
|
400 -> R.string.err_parameter
|
||||||
}
|
401 -> R.string.err_authentication
|
||||||
}
|
446 -> R.string.err_card_locked
|
||||||
}
|
448 -> R.string.err_bad_data
|
||||||
|
500 -> R.string.err_internal
|
||||||
|
else -> R.string.err_unknown
|
||||||
}
|
}
|
||||||
// Give user some time to read the error message
|
} catch (e: GeneralSecurityException) {
|
||||||
Thread.sleep(2000)
|
msgCode = R.string.err_internal
|
||||||
cancelAuth()
|
} catch (e: IOException) {
|
||||||
|
msgCode = R.string.err_reading_card
|
||||||
|
} catch (e: Exception) {
|
||||||
|
msgCode = R.string.err_unknown
|
||||||
} finally {
|
} finally {
|
||||||
adapter.disableReaderMode(activity)
|
adapter.disableReaderMode(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msgCode != 0) {
|
||||||
|
requireActivity().runOnUiThread {
|
||||||
|
var msg = getString(msgCode)
|
||||||
|
if (msgArg != null)
|
||||||
|
msg = String.format(msg, msgArg)
|
||||||
|
binding.timeCounter.text = msg
|
||||||
|
}
|
||||||
|
// Gives user some time to read the error message
|
||||||
|
Thread.sleep(2000)
|
||||||
|
cancelAuth()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, NfcAdapter.FLAG_READER_NFC_A, null)
|
}, NfcAdapter.FLAG_READER_NFC_A, null)
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,9 @@ package com.tarkvaraprojekt.mobileauthapp.NFC;
|
|||||||
import android.nfc.tech.IsoDep;
|
import android.nfc.tech.IsoDep;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.tarkvaraprojekt.mobileauthapp.auth.AuthAppException;
|
||||||
|
import com.tarkvaraprojekt.mobileauthapp.auth.InvalidPINException;
|
||||||
|
|
||||||
import org.bouncycastle.crypto.BlockCipher;
|
import org.bouncycastle.crypto.BlockCipher;
|
||||||
import org.bouncycastle.crypto.engines.AESEngine;
|
import org.bouncycastle.crypto.engines.AESEngine;
|
||||||
import org.bouncycastle.crypto.macs.CMac;
|
import org.bouncycastle.crypto.macs.CMac;
|
||||||
@@ -156,7 +159,7 @@ public class Comms {
|
|||||||
private byte[] getResponse(byte[] APDU, String log) throws IOException {
|
private byte[] getResponse(byte[] APDU, String log) throws IOException {
|
||||||
byte[] response = idCard.transceive(APDU);
|
byte[] response = idCard.transceive(APDU);
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
throw new RuntimeException(String.format("%s failed.", log));
|
throw new AuthAppException(String.format("%s failed.", log), 500);
|
||||||
}
|
}
|
||||||
Log.i(log, Hex.toHexString(response));
|
Log.i(log, Hex.toHexString(response));
|
||||||
return response;
|
return response;
|
||||||
@@ -204,7 +207,7 @@ public class Comms {
|
|||||||
// verify chip's MAC and return session keys
|
// verify chip's MAC and return session keys
|
||||||
MAC = getMAC(createAPDU(dataForMACIncomplete, publicKey.getEncoded(false), 65), keyMAC);
|
MAC = getMAC(createAPDU(dataForMACIncomplete, publicKey.getEncoded(false), 65), keyMAC);
|
||||||
if (!Hex.toHexString(response, 4, 8).equals(Hex.toHexString(MAC))) {
|
if (!Hex.toHexString(response, 4, 8).equals(Hex.toHexString(MAC))) {
|
||||||
throw new RuntimeException("Could not verify chip's MAC."); // *Should* never happen.
|
throw new AuthAppException("Could not verify chip's MAC.", 448); // *Should* never happen.
|
||||||
}
|
}
|
||||||
return new byte[][]{keyEnc, keyMAC};
|
return new byte[][]{keyEnc, keyMAC};
|
||||||
|
|
||||||
@@ -221,7 +224,7 @@ public class Comms {
|
|||||||
selectFile(FID, info);
|
selectFile(FID, info);
|
||||||
byte[] response = getResponse(new byte[0], readFile, "Read binary");
|
byte[] response = getResponse(new byte[0], readFile, "Read binary");
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
throw new RuntimeException(String.format("Could not read %s", info));
|
throw new AuthAppException(String.format("Could not read %s", info), 500);
|
||||||
}
|
}
|
||||||
return encryptDecryptData(Arrays.copyOfRange(response, 3, 19), Cipher.DECRYPT_MODE);
|
return encryptDecryptData(Arrays.copyOfRange(response, 3, 19), Cipher.DECRYPT_MODE);
|
||||||
}
|
}
|
||||||
@@ -290,7 +293,7 @@ public class Comms {
|
|||||||
private void selectFile(byte[] FID, String info) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, IOException {
|
private void selectFile(byte[] FID, String info) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, IOException {
|
||||||
byte[] response = getResponse(FID, selectFile, String.format("Select %s", info));
|
byte[] response = getResponse(FID, selectFile, String.format("Select %s", info));
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
throw new RuntimeException(String.format("Could not select %s", info));
|
throw new AuthAppException(String.format("Could not select %s", info), 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +318,7 @@ public class Comms {
|
|||||||
// select and read the personal data elementary files
|
// select and read the personal data elementary files
|
||||||
for (byte index : lastBytes) {
|
for (byte index : lastBytes) {
|
||||||
|
|
||||||
if (index > 15 || index < 1) throw new RuntimeException("Invalid personal data FID.");
|
if (index > 15 || index < 1) throw new AuthAppException("Invalid personal data FID.", 500);
|
||||||
FID[1] = index;
|
FID[1] = index;
|
||||||
|
|
||||||
// store the decrypted datum
|
// store the decrypted datum
|
||||||
@@ -348,9 +351,9 @@ public class Comms {
|
|||||||
|
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
if (response[response.length - 2] == 0x69 && response[response.length - 1] == (byte) 0x83) {
|
if (response[response.length - 2] == 0x69 && response[response.length - 1] == (byte) 0x83) {
|
||||||
throw new RuntimeException("Invalid PIN. Authentication method blocked.");
|
throw new AuthAppException("Invalid PIN. Authentication method blocked.", 446);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(String.format("Invalid PIN. Attempts left: %d.", response[response.length - 1] + 64));
|
throw new InvalidPINException(response[response.length - 1] + 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +382,7 @@ public class Comms {
|
|||||||
readCert[3] = (byte) (certificate.length % 256);
|
readCert[3] = (byte) (certificate.length % 256);
|
||||||
byte[] response = getResponse(new byte[0], readCert, "Read the certificate");
|
byte[] response = getResponse(new byte[0], readCert, "Read the certificate");
|
||||||
if (response[response.length - 2] == 0x6b && response[response.length - 1] == 0x00) {
|
if (response[response.length - 2] == 0x6b && response[response.length - 1] == 0x00) {
|
||||||
throw new RuntimeException("Wrong read parameters.");
|
throw new AuthAppException("Wrong read parameters.", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the range containing a portion of the certificate and decrypt it
|
// Set the range containing a portion of the certificate and decrypt it
|
||||||
@@ -414,7 +417,7 @@ public class Comms {
|
|||||||
|
|
||||||
byte[] response = getResponse(Env, MSESetEnv, "Set environment");
|
byte[] response = getResponse(Env, MSESetEnv, "Set environment");
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
throw new RuntimeException("Setting the environment failed.");
|
throw new AuthAppException("Setting the environment failed.", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalAuthenticate[4] = (byte) (0x1d + 16 * (token.length / 16));
|
InternalAuthenticate[4] = (byte) (0x1d + 16 * (token.length / 16));
|
||||||
@@ -422,7 +425,7 @@ public class Comms {
|
|||||||
response = getResponse(token, InternalAuthenticate, "Internal Authenticate");
|
response = getResponse(token, InternalAuthenticate, "Internal Authenticate");
|
||||||
|
|
||||||
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
if (response[response.length - 2] != (byte) 0x90 || response[response.length - 1] != 0x00) {
|
||||||
throw new RuntimeException("Signing the token failed.");
|
throw new AuthAppException("Signing the token failed.", 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] signature = encryptDecryptData(Arrays.copyOfRange(response, 3, 115), Cipher.DECRYPT_MODE);
|
byte[] signature = encryptDecryptData(Arrays.copyOfRange(response, 3, 115), Cipher.DECRYPT_MODE);
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
package com.tarkvaraprojekt.mobileauthapp.auth
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialised RuntimeException class for exceptions related to the mobile authentication app.
|
||||||
|
* Possible error codes can be found at
|
||||||
|
* https://github.com/TanelOrumaa/Estonian-ID-card-mobile-authenticator-POC/wiki/Error-codes
|
||||||
|
* @param message Error message
|
||||||
|
* @param code An error code defined in the project wiki
|
||||||
|
*/
|
||||||
|
open class AuthAppException(message: String, var code: Int) : RuntimeException(message)
|
@@ -0,0 +1,7 @@
|
|||||||
|
package com.tarkvaraprojekt.mobileauthapp.auth
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An AuthAppException for when the user entered CAN does not match the one read from the ID-card
|
||||||
|
* @see AuthAppException
|
||||||
|
*/
|
||||||
|
class InvalidCANException : AuthAppException("Invalid CAN", 400)
|
@@ -0,0 +1,10 @@
|
|||||||
|
package com.tarkvaraprojekt.mobileauthapp.auth
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An AuthAppException for when the user entered PIN is not correct
|
||||||
|
* @see AuthAppException
|
||||||
|
*/
|
||||||
|
class InvalidPINException(val remainingAttempts: Int) : AuthAppException(
|
||||||
|
"Invalid PIN" + (if (remainingAttempts>0) "" else ". Authentication method blocked."),
|
||||||
|
if (remainingAttempts>0) 401 else 446
|
||||||
|
)
|
@@ -19,7 +19,7 @@
|
|||||||
<string name="nfc_not_available">NFC is not turned on or is not supported by the phone</string>
|
<string name="nfc_not_available">NFC is not turned on or is not supported by the phone</string>
|
||||||
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
||||||
<string name="id_card_removed_early">ID card was removed too early</string>
|
<string name="id_card_removed_early">ID card was removed too early</string>
|
||||||
<string name="wrong_pin">Wrong PIN 1. Tries on the card left %s</string>
|
<string name="wrong_pin">Wrong PIN 1. %s tries left on the card</string>
|
||||||
|
|
||||||
<!-- string resources for HomeFragment -->
|
<!-- string resources for HomeFragment -->
|
||||||
<string name="pin_status_saved">PIN 1 saved</string>
|
<string name="pin_status_saved">PIN 1 saved</string>
|
||||||
@@ -75,8 +75,8 @@
|
|||||||
<string name="saved_can">CAN: %s</string>
|
<string name="saved_can">CAN: %s</string>
|
||||||
<string name="can_delete">Delete CAN</string>
|
<string name="can_delete">Delete CAN</string>
|
||||||
<string name="saved_pin">PIN1: %s</string>
|
<string name="saved_pin">PIN1: %s</string>
|
||||||
<string name="pin1_add">Add PIN1</string>
|
<string name="pin1_add">Add PIN 1</string>
|
||||||
<string name="pin1_delete">Delete PIN1</string>
|
<string name="pin1_delete">Delete PIN 1</string>
|
||||||
<string name="missing">not saved</string>
|
<string name="missing">not saved</string>
|
||||||
<string name="show">SHOW</string>
|
<string name="show">SHOW</string>
|
||||||
<string name="hide">HIDE</string>
|
<string name="hide">HIDE</string>
|
||||||
@@ -84,4 +84,13 @@
|
|||||||
<string name="menu_unavailable_message">Settings are currently unavailable</string>
|
<string name="menu_unavailable_message">Settings are currently unavailable</string>
|
||||||
<string name="can_deleted">CAN deleted</string>
|
<string name="can_deleted">CAN deleted</string>
|
||||||
<string name="pin_deleted">PIN 1 deleted</string>
|
<string name="pin_deleted">PIN 1 deleted</string>
|
||||||
|
|
||||||
|
<string name="err_unknown">Unknown error</string>
|
||||||
|
<string name="tag_lost">Connection between device and ID-card lost</string>
|
||||||
|
<string name="err_reading_card">Failed to read data from the ID-card</string>
|
||||||
|
<string name="err_internal">Internal error</string>
|
||||||
|
<string name="err_bad_data">Read bad data from the ID-card, try using the card again</string>
|
||||||
|
<string name="err_parameter">Required parameter is missing or invalid</string>
|
||||||
|
<string name="err_authentication">Failed to authenticate</string>
|
||||||
|
<string name="err_card_locked">Card locked</string>
|
||||||
</resources>
|
</resources>
|
@@ -18,7 +18,7 @@
|
|||||||
<string name="nfc_not_available">NFC ei ole sisse lülitatud või puudub telefonil NFC võimekus</string>
|
<string name="nfc_not_available">NFC ei ole sisse lülitatud või puudub telefonil NFC võimekus</string>
|
||||||
<string name="nfc_reading_error">Sisestatud CAN ei ole vastavuses ID kaardiga</string>
|
<string name="nfc_reading_error">Sisestatud CAN ei ole vastavuses ID kaardiga</string>
|
||||||
<string name="id_card_removed_early">ID kaart eemaldati liiga vara</string>
|
<string name="id_card_removed_early">ID kaart eemaldati liiga vara</string>
|
||||||
<string name="wrong_pin">Vale PIN 1. ID kaardil PIN 1 sisetamise kordi alles: %s</string>
|
<string name="wrong_pin">Vale PIN 1. ID kaardil PIN 1 sisetamise katseid järel: %s</string>
|
||||||
|
|
||||||
<!-- string resources for HomeFragment -->
|
<!-- string resources for HomeFragment -->
|
||||||
<string name="pin_status_saved">PIN 1 on salvestatud</string>
|
<string name="pin_status_saved">PIN 1 on salvestatud</string>
|
||||||
@@ -83,4 +83,13 @@
|
|||||||
<string name="menu_unavailable_message">Seaded pole hetkel saadaval</string>
|
<string name="menu_unavailable_message">Seaded pole hetkel saadaval</string>
|
||||||
<string name="can_deleted">CAN kustatud</string>
|
<string name="can_deleted">CAN kustatud</string>
|
||||||
<string name="pin_deleted">PIN 1 kustatud</string>
|
<string name="pin_deleted">PIN 1 kustatud</string>
|
||||||
|
|
||||||
|
<string name="err_unknown">Tundmatu viga</string>
|
||||||
|
<string name="tag_lost">Ühendus seadme ja kaardi vahel katkes</string>
|
||||||
|
<string name="err_reading_card">Ei saanud ID-kaardilt andmeid lugeda</string>
|
||||||
|
<string name="err_internal">Rakendusesisene viga</string>
|
||||||
|
<string name="err_bad_data">ID-kaardilt loeti vigased andmed, proovi uuesti kaarti kasutada</string>
|
||||||
|
<string name="err_parameter">Vigane või puuduv parameeter</string>
|
||||||
|
<string name="err_authentication">Autentimine ebaõnnestus</string>
|
||||||
|
<string name="err_card_locked">Kaart lukus</string>
|
||||||
</resources>
|
</resources>
|
@@ -17,7 +17,7 @@
|
|||||||
<string name="nfc_not_available">NFC is not turned on or is not supported by the phone</string>
|
<string name="nfc_not_available">NFC is not turned on or is not supported by the phone</string>
|
||||||
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
<string name="nfc_reading_error">The provided CAN does not match the ID card</string>
|
||||||
<string name="id_card_removed_early">ID card was removed too early</string>
|
<string name="id_card_removed_early">ID card was removed too early</string>
|
||||||
<string name="wrong_pin">Wrong PIN 1. Tries on the card left %s</string>
|
<string name="wrong_pin">Wrong PIN 1. %s tries left on the card</string>
|
||||||
|
|
||||||
<!-- string resources for HomeFragment -->
|
<!-- string resources for HomeFragment -->
|
||||||
<string name="pin_status_saved">PIN 1 saved</string>
|
<string name="pin_status_saved">PIN 1 saved</string>
|
||||||
@@ -82,4 +82,13 @@
|
|||||||
<string name="menu_unavailable_message">Settings are currently unavailable</string>
|
<string name="menu_unavailable_message">Settings are currently unavailable</string>
|
||||||
<string name="can_deleted">CAN deleted</string>
|
<string name="can_deleted">CAN deleted</string>
|
||||||
<string name="pin_deleted">PIN 1 deleted</string>
|
<string name="pin_deleted">PIN 1 deleted</string>
|
||||||
|
|
||||||
|
<string name="err_unknown">Unknown error</string>
|
||||||
|
<string name="tag_lost">Connection between device and ID-card lost</string>
|
||||||
|
<string name="err_reading_card">Failed to read data from the ID-card</string>
|
||||||
|
<string name="err_internal">Internal error</string>
|
||||||
|
<string name="err_bad_data">Read bad data from the ID-card, try using the card again</string>
|
||||||
|
<string name="err_parameter">Required parameter is missing or invalid</string>
|
||||||
|
<string name="err_authentication">Failed to authenticate</string>
|
||||||
|
<string name="err_card_locked">Card locked</string>
|
||||||
</resources>
|
</resources>
|
@@ -1 +0,0 @@
|
|||||||
#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}#nav{padding:30px}#nav a{font-weight:700;color:#2c3e50}#nav a.router-link-exact-active{color:#42b983}.container>div[data-v-2dcb24ca]{margin-top:2vh}.loginButton[data-v-2dcb24ca]{height:4vh;width:20vh;line-height:3vh}.loginButton>p[data-v-2dcb24ca]{font-size:3vh;text-align:center}#canvas[data-v-2dcb24ca]{height:30vh;width:30vh}nav[data-v-21165a6a]{height:5vh}div[data-v-cd8fea1a]{margin-top:2vh}
|
|
File diff suppressed because one or more lines are too long
BIN
demoBackend/src/demo-website/dist/favicon.ico
vendored
BIN
demoBackend/src/demo-website/dist/favicon.ico
vendored
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
1
demoBackend/src/demo-website/dist/index.html
vendored
1
demoBackend/src/demo-website/dist/index.html
vendored
@@ -1 +0,0 @@
|
|||||||
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>demo-website</title><link href="/css/app.eb039c1f.css" rel="preload" as="style"><link href="/css/chunk-vendors.a251e031.css" rel="preload" as="style"><link href="/js/app.c2a68e49.js" rel="preload" as="script"><link href="/js/chunk-vendors.22b03028.js" rel="preload" as="script"><link href="/css/chunk-vendors.a251e031.css" rel="stylesheet"><link href="/css/app.eb039c1f.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but demo-website doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.22b03028.js"></script><script src="/js/app.c2a68e49.js"></script></body></html>
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user