# Page History

## Key

• This line was removed.
• Formatting was changed.

An encoding description contains the information for the electronic personalization of a card. You import the encoding description from a file. This can be used in Smart ID Identity Manager.

This article describes how you create descriptions for Nexus Personal Desktop Client.

Expandall

# Mandatory middleware configuration

After installing and updating Nexus Personal Desktop Client, make the following configuration changes for proper operation of the Nexus Personal Desktop Client middleware with Identity Manager:

Expand
title Configure PIN encryption certificate
1. Edit C:\Program Files (x86)\Personal\config\iD2ppa.cfg and set the following (with the appropriate path instead of the example given here):

Code Block
title Example: Set path to PIN encryption certificate
[PIN Encryption]
File=C:\path\to\the\certificate.crt

Note

The certificate you reference here can be an arbitrary dummy certificate, unless you need a specific certificate for non-Identity Manager use-cases.

Expand
title Disable caching of card content

Caching can cause problems during encoding due to outdated data, so you have to disable it.

1. Set the following in C:\Program Files (x86)\Personal\config\Personal.cfg (system-wide base config) and/or in %APPDATA%\Personal\config\Personal.cfg (per-user override config - this takes precedence, if set in both):

Code Block
title Disable caching of card content
[Cache]
CacheValidity=0

# Encodings

Expand
title Middleware DLL configuration

As the 64 bit version of the Nexus Personal Desktop Client middleware DLL cannot initialize cards, it is necessary to set only the path to the 32 bit DLL in the encoding description.

1. Set the following in the encoding description (note the explicit use of PKCS11LibraryWindows32 and the absence of PKCS11Library and PKCS11LibraryWindows64 definitions):

Code Block
title Configure DLL
[Description]
PKCS11LibraryWindows32=C:/Program Files (x86)/Personal/bin/personal.dll

Note

For encodings that use JPKIEncoder (usually via Nexus Card SDK), you also need to set the JAVA_HOME environment variable to the root folder of a 32 bit JRE, as a 64 bit JRE cannot load 32 bit DLLs.

This does not apply for encodings using Smart ID Desktop app, as it does not use Java.

Expand

Nexus Personal Desktop Client can create cards which use different credentials to log in as administrative user (user type CKU_SO as defined in the PKCS#11 standard).

Depending on the settings in the card profile (CPF) used to initialize the card, either the PUK or the operator PIN will be used.

In case of the latter, the PUK is only used for the Personal-specific PIN unblocking method, but not as administrative login.

1. Define like this in the encoding description:

Code Block
[Description]
Operator_Pin=...
OperatorPinIsSOCredential=#true

Description of the elements:

ElementDescription
OperatorPinIsSOCredential=The default value is false, which works for the standard Identity Manager PCM encodings, that use the PUK as SO credential.

2. Instead of setting the value to true or false directly in the the encoding description file (the DSC file), you can also use a mapped field, like this:

Code Block
[Fields]
UseOpPin=

[Description]
Operator_Pin=...
OperatorPinIsSOCredential=UseOpPin

Expand
title Limited support for changing the PUK

Nexus Personal Desktop Client 5.7.1 or lower does not support changing the PUK.

Nexus Personal Desktop Client 5.7.2 or higher does support changing the PUK, but only for specific cards:

• Cosmo 7
• Cosmo 8.2

For all other cards there is no way to change the PUK with this middleware.

Note

This feature requires Identity Manager 21.04.3 or higher - changing the PUK with Nexus Personal Desktop client is blocked in previous Identity Manager versions.

Expand
title Set CMSCardSerialNumber with Personal Desktop Client

The serial number is created with a number range in Identity Manager and then set on the card, the certificates and in the CM token. The handling of the card secrets is done on the server by CardProductionPostProcessor. This ensures that both possible certificate request processes (P12 requests, P10 requests) together with token creation on Nexus Certificate Manager can be handled.

1. Define like this in the encoding description:

Code Block
[Encoding]
Type=1024,Chip
Devices=8710

[Fields]
AppList=
ICCSN=
PIN_FIELD=
PUK_FIELD=
OP_PIN_FIELD=
P12CERTIFICATE_B=
PRIME_FIELD_WITH_CARD_SERIAL=

[Description]
PKCS11LibraryWindows32=C:/Program Files (x86)/Personal/bin/personal.dll
iccsnfield=ICCSN
UseSelectCriteriaIccsn=false
InitToken=true
InitialPUK=PUK_FIELD
Operator_Pin=OP_PIN_FIELD
InitialLabel=#01234567890123456789012345678901
ChipProfile=PRIME_CardOS5_personal.cpf
PIN=PIN_FIELD
CMSCardSerialNumber=PRIME_FIELD_WITH_CARD_SERIAL
ApplicationListField=AppList

[Application_A]
CardSerialNumberField=PRIME_FIELD_WITH_CARD_SERIAL
CertTempl=EncHardCodedValuesP10
ObjectCriteria=CKO_PUBLIC_KEY,CKA_LABEL,string,"Digital Signature"

[Application_B]
CardSerialNumberField=PRIME_FIELD_WITH_CARD_SERIAL
CertTempl=EncHardCodedValues
KeyArchivalRequest=true
WriteP12Data=true
Certificate=P12CERTIFICATE_B
P12PASSWORD=P12PASSWORD_B

Description of the elements:

ElementDescription
InitToken=trueThis is the trigger to run the CardProductionPostProcessor which actually sets the card secrets for the token on the Nexus CM.
CMSCardSerialNumber=PRIME_FIELD_WITH_CARD_SERIALMaps the card serial number to be written on the physical smart card and the token on the Nexus CM for setting the card secrets.

These two mappings are used to ensure that a generated (either by Identity Manager or by Certificate Manager) card serial number can be used over several applications.

Usually you need an administrative login to write the card serial number. This mechanism is described in Certificates and keys in Identity Manager (heading "Create external card serial number and reuse value (CM)".)

Expand
title Delete token profile

There is a flag that allows to delete the entire token profile, and return the card to the uninitialized state. This is done by using a virtual object called "Card Eraser" available on certain cards (for example, CardOS 4.4, 5.x, certain Gemalto cards...).

1. Define like this in the encoding description:

Code Block
[Description]
DeleteProfile=true

This flag is currently not supported on other middlewares and its use will result in an error.

If a PIN or PUK is also passed with the encoding description, the highest of those is used to log in, otherwise, an attempt to delete anonymously is done.

Neither PIN nor PUK provides a benefit over anonymous deletion - there is a third credential (operator PIN), which Personal Desktop Client requires to delete the card, but Identity Manager does not yet support to log in with that.

Whether or not you will be able to anonymously erase the card depends on the CPF file that was used to initialize the card.

Examples

• MakeCardEraseable() at the start and BurnFuse() at the end => anonymous erase should work
• Neither MakeCardEraseable() at the start nor BurnFuse()  => anonymous erase should work
• BurnFuse() at the end, MakeCardEraseable() missing => anonymous erase will fail

An exception will be thrown if the "Card Eraser" object is not found.

Expand

Note

This feature requires the use of Smart ID Desktop App as encoding application. Encoding via JPKIEncoder through Nexus Card SDK is not supported.

When pre-personalizing a card via Key Generation System (KGS) (see Produce smart cards in Certificate Manager), you can store a set of PINs on the card, which are encrypted with the public key of a so-called PIN Encryption Certificate.
Identity Manager can then read and decrypt those PINs, for example, to create a PIN letter for the user.

An example card profile (CPF) for pre-personalization could look like this:

Code Block
title Example: pinblob_demo_sketch.cpf true
MakeCardEraseable()
CardModel 'SIEMENS50'
PROFILENAME = 'P15_Siemens'
PERSINFO_PUT_PROFILENAME(PROFILENAME)

; prepare credentials to put into the "Encrypted PINs" blob... (you can skip those you don't need)
SEC_PIN1 = ... ; TODO: define PIN1 (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PIN1)

SEC_PIN2 = ... ; TODO: define PIN2 (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PIN2)

SEC_PIN3 = ... ; TODO: define PIN3 (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PIN3)

SEC_PUK = ... ; TODO: define PUK (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PUK)

SEC_PUK1 = ... ; TODO: define PUK1 (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PUK1)

SEC_PUK2 = ... ; TODO: define PUK2 (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_PUK2)

SEC_OP = ... ; TODO: define OP PIN (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_OP)

SEC_MAN = ... ; TODO: define MAN PIN (e.g. via SECRANDOM(...))
PERSINFO_PUT_SEC(SEC_MAN)

; ...now create the PIN blob...
PERSINFO_ENCRYPT_SEC()

; start files setup...
MasterFile

;..Directory DFPKCS15
;
;(RID = 0x{A0 00 00 63}, App='PKCS 15')
CreateDf DFPKCS15 id=0x5015 maxsize=22000 update=always create=always \
aid=0x{A0 00 00 00 63 50 4B 43 53 2D 31 35}

CreateEf EFODF     id=0x5031 maxsize=auto read=always update=always

CreateEf EFCDF1    id=0x4441 maxsize=1700 read=always update=always
CreateEf EFCERT1   id=0x4541 maxsize=6000 read=always update=always

EndDF  ;DFPKCS15

Endfile

File Static EFODF
data= 0x{
A4 0A                       ; PKCS15Certificates (read only)
30 08                    ; path alternative
04 06                 ;
3F 00 50 15 44 41
}
Endfile

File Static EFCDF1
data= 0x{
30 2F                               ; Cert 1
30 1A                            ; Common object attributes
0C 11                         ; Label: Digital Signature
44 69 67 69 74 61 6C 20 53 69 67 6E 61 74 75 72 65
03 02 06 40                   ; Flags: not private, modifiable
04 01 01                         ; authentication id
30 03                            ; Common certificate attributes
04 01 11                      ; id
A1 0C                            ; X.509 certificate attributes
30 0A
30 08                      ; certificate value indirect
04 06
3F 00 50 15 45 41
}
Endfile

File Dynamic EFCERT1
; here the blob is written to the EFCERT1 file, it will containing a data object called "Encrypted PINs"
data = PERSINFO_SEC()   ; there are also variants like PERSINFO_PUT_PUBRSA_AND_SEC() which add extra data to the same file
Endfile

; and now the files are created
CreateFiles()


See the PPA Scripting Language documentation PDF for more details (available in the doc.zip file for every Personal Desktop Client release in the support portal.)

# Prerequisites

Expand
title Configure private keys

You must configure the private keys matching any PIN encryption certificate you want to decrypt PINs for.

1. Edit the following config files in Identity Manager Operator:
1. Open the <tomcat>/webapps/<application>/WEB-INF/classes/engineSignEncrypt.xml file (see Sign and encrypt engine in Identity Manager for more information) and define key entries and corresponding descriptors. For PIN decryption, always use descriptor types with algorithm="RSA" and no further parameters aside from the key name. See the example below:

Code Block
language xml Example: extract of engineSignEncrypt.xml
<?xml version="1.0" encoding="UTF-8"?>
<engineSignEncrypt>
<descriptors>
...
<descriptor name="PinKeyDescA" version="1">
<type algorithm="RSA" key="pinKeyA" />
</descriptor>
<descriptor name="PinKeyDescB" version="1">
<type algorithm="RSA" key="pinKeyB" />
</descriptor>
...
</descriptors>
<keys>
...
<!-- this key is loaded from a file -->
<key name="pinKeyA">
<type name="pkcs12"
locationValue="classpath:pinKeyA.p12"
pin="432809864240763"/>
</key>
<!-- this key resides in a HSM for improved security -->
<key name="pinKeyB">
<type name="HSM"
locationValue="C:\Program Files\Utimaco\CryptoServer\Lib\cs_pkcs11_R2"
pin="10297385314563206"
alias="myOtherPinKey"
slot="3" />
</key>
...
</keys>
</engineSignEncrypt>



2. Open the <tomcat>/webapps/<application>/WEB-INF/classes/system.properties file and specify the parameter pinBlobDecryptor.keyDescriptorNames: add a comma-separated list to the parameter, of key descriptor names for all those keys you want to decrypt PINs with. See the example below:

Code Block
title Example: extract of engineSignEncrypt.xml
<?xml version="1.0" encoding="UTF-8"?>
<engineSignEncrypt>
<descriptors>
...
<descriptor name="PinKeyDescA" version="1">
<type algorithm="RSA" key="pinKeyA" />
</descriptor>
<descriptor name="PinKeyDescB" version="1">
<type algorithm="RSA" key="pinKeyB" />
</descriptor>
...
</descriptors>
<keys>
...
<!-- this key is loaded from a file -->
<key name="pinKeyA">
<type name="pkcs12"
locationValue="classpath:pinKeyA.p12"
pin="432809864240763"/>
</key>
<!-- this key resides in a HSM for improved security -->
<key name="pinKeyB">
<type name="HSM"
locationValue="C:\Program Files\Utimaco\CryptoServer\Lib\cs_pkcs11_R2"
pin="10297385314563206"
alias="myOtherPinKey"
slot="3" />
</key>
...
</keys>
</engineSignEncrypt>



2. When using Docker, make sure you mount any necessary P12 files into appropriate locations inside the container (see docker-compose.yml volume mappings), in addition to editing the config/signencrypt.xml file. See the example below:

Code Block
language yml Example: extract of docker-compose.yml
...
environment:
...
- 'SYSTEM_PROPERTIES={
"pinBlobDecryptor.keyDescriptorNames": "PinKeyA,PinKeyB",
...
}'
...
volumes:
- "/path/to/pinKeyA.p12:/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/pinKeyA.p12:ro"
...

Note

Support for multi-tenancy is limited: The PIN blob decryptor configuration is global across all tenants, that is, every tenant has access to all of the keys.

# Configure encoding description

1. To read any of the possible PINs (PIN1, PIN2, PIN3, PUK, PUK1, PUK2, OP pin, MAN pin), configure your encoding description according to the example below:

Code Block
[Encoding]
Type=1024,Chip
Devices=8711

[Fields]
DecryptedCardPin_PIN1=
DecryptedCardPin_PIN2=
DecryptedCardPin_PIN3=
DecryptedCardPin_PUK=
DecryptedCardPin_PUK1=
DecryptedCardPin_PUK2=
DecryptedCardPin_OP=
DecryptedCardPin_MAN=

[Description]
PKCS11LibraryWindows32=C:/Program Files (x86)/Personal/bin/personal.dll
# you can use any subset of the CardPinDecryption_Output_* parameters below, the others not specified will be ignored
CardPinDecryption_Output_PIN1=DecryptedCardPin_PIN1
CardPinDecryption_Output_PIN2=DecryptedCardPin_PIN2
CardPinDecryption_Output_PIN3=DecryptedCardPin_PIN3
CardPinDecryption_Output_PUK=DecryptedCardPin_PUK
CardPinDecryption_Output_PUK1=DecryptedCardPin_PUK1
CardPinDecryption_Output_PUK2=DecryptedCardPin_PUK2
CardPinDecryption_Output_OP=DecryptedCardPin_OP
CardPinDecryption_Output_MAN=DecryptedCardPin_MAN

# you MUST NOT specify any encoding application if you use this feature - it can be safely used together with reading the ICCSN


2. When you configure the mapping of the encoding fields, you have to map every DSC field that is connected to a CardPinDecryption_Output_ parameter into an encrypted field from a data pool, and the "Read" flag has to be checked. For example, if you have a field called "PukRef" of type Encrypted Field in the datapool "Card", you can map the DSC field to "${Card_PukRef}". Note Any attempt to read an encrypted PIN into a plain-text field or process variable will trigger an error message and prevent the encoding from being executed, in order to prevent exposure of sensitive credentials. Note Reading the encrypted PINs is executed in the finalization command block, like reading ICCSN and ATR. Its output cannot be used to log into the card during the same encoding. Therefore use a dedicated encoding description for reading and storing the encrypted PINs combined only with other steps that do not require logging into the card. # Error messages Expand title Matching Private Key For PIN Blob Not Found • The encoding task will return an error in the process map, for example like this: Code Block title Example: Return error in the process map  ProductionResultErrorMsg=Error Accessing Smartcard ( (PkiUtilsException): java.lang.IllegalArgumentException: No decryption key found matching #HEX_KEY_ID_GOES_HERE) Meta_ProductionResult=error • The process can react to these variables. • If that error happens, you are most likely either dealing with an unknown card or have some misconfiguration (for example incomplete or missing descriptor list in system.properties). Expand title No PIN Values Returned From Encoding • This can happen if you read from a card which does not contain encrypted PINs, for example, a blank card. • Check the DSC to make sure you specified the correct output fields, and that the "Read" flag is checked in the field mapping. Expand title Incorrect Field Mapping In Encoding Description • Only encrypted datapool fields are allowed as output for encrypted PINs. Make sure that is the case and that you use the correct expression syntax:${DataPoolName_FieldName}
• For security reasons you cannot read into plain-text datapool fields or process variables.

# Troubleshooting

Expand
title Certain operations fail if virtual smartcard is present

The If a virtual smartcards are present on Windows, this can cause failures when using the Personal Desktop Client middleware can sometimes get confused by virtual smartcards on Windows (for example, GENERAL_ERROR on C_GetProperty). To avoid this, you can exclude the respective reader names.

1. Set the following in C:\Program Files (x86)\Personal\config\Personal.cfg (system-wide base config) and/or in %APPDATA%\Personal\config\Personal.cfg (per-user override config - this takes precedence, if set in both):

Code Block
[Reader]
SkipReader=Microsoft Virtual Smart Card .*

Expand
title InitTokenPPA fails

If the above this error shows up in the jpki_encoder log, when trying to initialize a card, this is usually caused by one of the following:

• PIN encryption certificate is not correctly configured in the middleware
→ follow the instructions under section "Configure PIN encryption certificate" above.
• Card profile configuration file (CPF) used in the Identity Manager encoding description does not match the card type to be initialized
use a CPF file that is properly configured for the given card type.
• JPKIEncoder runs on a 64 bit JRE or the DLL path is incorrect
follow the instructions under section "Middleware DLL configuration" above.

Expand
title Miscellaneous error causes

Other errors can be caused by the following:

• Caching is erroneously enabled
follow the instructions under section "Disable caching of card content" above
• The wrong middleware DLL is set in the encoding description
follow the instructions under section "Middleware DLL configuration" above.
• JAVA_HOME is not set or points to the wrong path
follow the instructions under section "Middleware DLL configuration" above.

Expand
title Logging

By default log files are written to %APPDATA%\Personal\log\ .