Updated on 2026-08-14
This commit is contained in:
parent
0ad47fca68
commit
5f7612ca57
4 changed files with 60 additions and 14 deletions
|
|
@ -262,14 +262,12 @@ class CardManager(
|
|||
* during personalization.
|
||||
* @param cardId this parameter will set up CID, Unique Tangem card ID.
|
||||
*/
|
||||
fun personalize(config: CardConfig,
|
||||
cardId: String,
|
||||
callback: (result: TaskEvent<Card>) -> Unit) {
|
||||
fun personalize(config: CardConfig, callback: (result: TaskEvent<Card>) -> Unit) {
|
||||
if (this.config.issuer == null) {
|
||||
callback(TaskEvent.Completion(TaskError.IssuerIsRequired()))
|
||||
return
|
||||
}
|
||||
val personalizationCommand = PersonalizeCommand(config, cardId)
|
||||
val personalizationCommand = PersonalizeCommand(config)
|
||||
val task = SingleCommandTask(personalizationCommand)
|
||||
task.performPreflightRead = false
|
||||
runTask(task, callback = callback)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.commands.Card
|
|||
import com.tangem.commands.CardData
|
||||
import com.tangem.commands.CommandSerializer
|
||||
import com.tangem.commands.personalization.entities.Issuer
|
||||
import com.tangem.commands.personalization.util.CardIdCreator
|
||||
import com.tangem.common.CardEnvironment
|
||||
import com.tangem.common.apdu.CommandApdu
|
||||
import com.tangem.common.apdu.Instruction
|
||||
|
|
@ -27,7 +28,7 @@ import com.tangem.tasks.TaskError
|
|||
* during personalization.
|
||||
* @param cardId this parameter will set up CID, Unique Tangem card ID.
|
||||
*/
|
||||
class PersonalizeCommand(private val config: CardConfig, private val cardId: String) : CommandSerializer<Card>() {
|
||||
class PersonalizeCommand(private val config: CardConfig) : CommandSerializer<Card>() {
|
||||
|
||||
override fun serialize(cardEnvironment: CardEnvironment): CommandApdu {
|
||||
if (cardEnvironment.issuer == null || cardEnvironment.manufacturerKeyPair == null) {
|
||||
|
|
@ -36,9 +37,8 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str
|
|||
return CommandApdu(
|
||||
Instruction.Personalize,
|
||||
serializePersonalizationData(
|
||||
cardId, config,
|
||||
cardEnvironment.issuer, cardEnvironment.manufacturerKeyPair.privateKey,
|
||||
cardEnvironment.acquirerKeyPair?.publicKey),
|
||||
config, cardEnvironment.issuer,
|
||||
cardEnvironment.manufacturerKeyPair.privateKey, cardEnvironment.acquirerKeyPair?.publicKey),
|
||||
encryptionKey = devPersonalizationKey
|
||||
)
|
||||
}
|
||||
|
|
@ -99,13 +99,14 @@ class PersonalizeCommand(private val config: CardConfig, private val cardId: Str
|
|||
)
|
||||
}
|
||||
|
||||
private fun serializePersonalizationData(cardId: String, config: CardConfig,
|
||||
issuer: Issuer, manufacturerPrivateKey: ByteArray,
|
||||
private fun serializePersonalizationData(config: CardConfig, issuer: Issuer,
|
||||
manufacturerPrivateKey: ByteArray,
|
||||
acquirePublicKey: ByteArray?
|
||||
): ByteArray {
|
||||
val cardId = CardIdCreator.create(config.series, config.startNumber)
|
||||
?: throw TaskError.SerializeCommandError()
|
||||
val tlvBuilder = TlvBuilder()
|
||||
tlvBuilder.append(TlvTag.CardId, cardId)
|
||||
|
||||
tlvBuilder.append(TlvTag.CurveId, config.curveID)
|
||||
tlvBuilder.append(TlvTag.MaxSignatures, config.maxSignatures)
|
||||
tlvBuilder.append(TlvTag.SigningMethod, config.signingMethod)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.commands.personalization.util
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class CardIdCreator {
|
||||
|
||||
companion object {
|
||||
private val Alf = "ABCDEF0123456789"
|
||||
|
||||
fun create(nsSeries: String?, number: Long): String? {
|
||||
val series = nsSeries ?: return null
|
||||
if (number <= 0 || (series.length != 2 && series.length != 4)) return null
|
||||
if (!checkSeries(series)) return null
|
||||
|
||||
val tail = if (series.length == 2) String.format("%013d", number) else String.format("%011d", number)
|
||||
val cardId = series + tail
|
||||
return completeCardID(cardId)
|
||||
}
|
||||
|
||||
private fun checkSeries(series: String): Boolean {
|
||||
val containsList = series.filter { Alf.contains(it) }
|
||||
return containsList.length == series.length
|
||||
}
|
||||
|
||||
private fun completeCardID(imCardId: String): String? {
|
||||
var cardId = imCardId
|
||||
cardId = cardId.replace(" ", "")
|
||||
if (cardId.length != 15 || Alf.indexOf(cardId[0]) == -1 || Alf.indexOf(cardId[1]) == -1)
|
||||
return null
|
||||
|
||||
cardId += "0"
|
||||
val length = cardId.length
|
||||
var sum = 0
|
||||
for (i in 0 until length) {
|
||||
// get digits in reverse order
|
||||
var digit: Int
|
||||
val cDigit = cardId[length - i - 1]
|
||||
digit = if (cDigit in '0'..'9') cDigit - '0' else cDigit - 'A'
|
||||
|
||||
// every 2nd number multiply with 2
|
||||
if (i % 2 == 1) digit *= 2
|
||||
sum += if (digit > 9) digit - 9 else digit
|
||||
}
|
||||
val lunh = (10 - sum % 10) % 10
|
||||
return cardId.substring(0, 15) + String.format("%d", lunh)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -154,9 +154,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
btn_read_write_user_data?.setOnClickListener { startActivity(Intent(this, TestUserDataActivity::class.java)) }
|
||||
btn_personalize?.setOnClickListener { _ ->
|
||||
cardManager.personalize(
|
||||
CardConfig.init(application), "BB00000000000395"
|
||||
) {
|
||||
cardManager.personalize(CardConfig.init(application)) {
|
||||
when (it) {
|
||||
is TaskEvent.Completion -> {
|
||||
if (it.error != null) runOnUiThread { tv_card_cid?.text = it.error!!::class.simpleName }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue