Working with card readers - siimsuu1/MOPP-iOS GitHub Wiki

Aside from signing documents with ID-card, you can use MoppLib to read data from ID-card.

Discovering and connecting supported card readers is coordinated by MoppLibCardReadersManager. startDiscoveringReaders must be first called to start card readers discovery. Because discovering card readers might be battery-intensive operation, stopDiscoveringReaders should be called to stop the discovery.

Supported card readers

Card reader status

Card reader status is received from MoppLibCardReaderManagerDelegate's moppLibCardReaderStatusDidChange method. There are three possible statuses:

  • ReaderNotConnected - There are no supported card readers discovered
  • ReaderConnected - Card reader is discovered and successfully connected to the device
  • CardConnected - Card reader is connected and ID-card is found to be inserted into the reader

It is also possible to check card reader status from outside the MoppLibCardReaderManager using isReaderConnected method:

BOOL isConnected = [MoppLibCardActions isReaderConnected]

When reader is connected, you may also want to know if card is inserted properly in card reader, to provide more information to your user using isCardInserted method:

[MoppLibCardActions isCardInserted:^(BOOL isInserted) {
NSString *result = isInserted ? @"Card is inserted" : @"Card is not found";
    NSLog(@"%@", result);
}];

MoppLib can also send you notifications when card status changes. To get notifications, add observer for kMoppLibNotificationReaderStatusChanged:

- (void)viewDidLoad {
  [super viewDidLoad];
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cardStatusChanged) name:kMoppLibNotificationReaderStatusChanged object:nil];
}

- (void)cardStatusChanged {
  BOOL isReaderConnected = [MoppLibCardActions isReaderConnected];
  
  [MoppLibCardActions isCardInserted:^(BOOL isInserted) {
    // Card status updated
  }];
}

Reading public data on card

You can get some data from ID-card, that is publicly available. This includes things like card owner name, birth date, document number etc.

[MoppLibCardActions cardPersonalDataWithViewController:self success:^(MoppLibPersonalData *personalData) {
  NSLog(@"First name line 1: %@", personalData.firstNameLine1);
  NSLog(@"First name line 2: %@", personalData.firstNameLine2);
  NSLog(@"Surname: %@", personalData.surname);
  NSLog(@"Expiry: %@", personalData.expiryDate);
  NSLog(@"Document number: %@", personalData.documentNumber);
  NSLog(@"Personal identification code: %@", personalData.personalIdentificationCode);
  NSLog(@"Birth date: %@", personalData.birthDate);
  NSLog(@"Nationality: %@", personalData.nationality);
  NSLog(@"Sex: %@", personalData.sex);
  NSLog(@"Date issued: %@", personalData.dateIssued);
  NSLog(@"Permit type: %@", personalData.residentPermitType);
  NSLog(@"Notes 1: %@", personalData.notes1);
  NSLog(@"Notes 2: %@", personalData.notes2);
  NSLog(@"Notes 3: %@", personalData.notes3);
  NSLog(@"Notes 4: %@", personalData.notes4);
    
} failure:^(NSError *error) {
  NSLog(@"Failed to get personal data: %@", error);
}];

Reading data from card can be time-consuming. If you don't need all available data, then you can choose to get only the set of most important values.

[MoppLibCardActions minimalCardPersonalDataWithViewController:self success:^(MoppLibPersonalData *personalData) {
  NSLog(@"First name line 1: %@", personalData.firstNameLine1);
  NSLog(@"First name line 2: %@", personalData.firstNameLine2);
  NSLog(@"Surname: %@", personalData.surname);
  NSLog(@"Expiry: %@", personalData.expiryDate);
  NSLog(@"Document number: %@", personalData.documentNumber);
  NSLog(@"Personal identification code: %@", personalData.personalIdentificationCode);
  NSLog(@"Birth date: %@", personalData.birthDate);
  NSLog(@"Nationality: %@", personalData.nationality);

} failure:^(NSError *error) {
  NSLog(@"Failed to get personal data: %@", error);
}];

Certificates data

There are two certificates on ID-card - authentication and signing certificate. You can get some basic data like expiry dates from them.

For signing certificate use signingCertificate method:

[MoppLibCardActions signingCertificateWithSuccess:^(MoppLibCertData *data) {
  NSLog(@"Is valid: %d", data.isValid);
  NSLog(@"Expiry date: %@", data.expiryDate);
  NSLog(@"Usage count: %i", data.usageCount);

} failure:^(NSError *error) {
  NSLog(@"Failed to get cert: %@", error);
}];

For authentication certificate use authenticationCertificate method:

[MoppLibCardActions authenticationCertificateWithSuccess:^(MoppLibCertData *data) {
  NSLog(@"Is valid: %d", data.isValid);
  NSLog(@"Expiry date: %@", data.expiryDate);
  NSLog(@"Usage count: %i", data.usageCount);
  NSLog(@"Email: %@", data.email);

} failure:^(NSError *error) {
  NSLog(@"Failed to get cert: %@", error);
}];

PIN retry counters

PIN and PUK codes can get blocked when invalid code is used for some actions. It is important to notify user in that case, so they would know when they have to take action in order to unblock blocked code. It is not possible to continue to use certain functionality, like document signing, when PIN is blocked.

MoppLib provides methods for getting retry counter value from ID-card. The number returned represents how many retries user has left for each code. When count reaches 0, then that particular code is blocked and can't be used anymore until user unblocks it. Unblock actions are not available for third-party applications. User will have to use one of RIA DigiDoc applications to unblock.

[MoppLibCardActions pukRetryCountWithViewController:self success:^(NSNumber *count) {
  NSLog(@"PUK retry count: %@", count);
} failure:^(NSError *error) {
  NSLog(@"Failed to get PUK retry count: %@", error);
}];
  
[MoppLibCardActions pin1RetryCountWithViewController:self success:^(NSNumber *count) {
  NSLog(@"PIN1 retry count: %@", count);
} failure:^(NSError *error) {
  NSLog(@"Failed to get PIN1 retry count: %@", error);
}];
  
[MoppLibCardActions pin2RetryCountWithViewController:self success:^(NSNumber *count) {
  NSLog(@"PIN2 retry count: %@", count);
} failure:^(NSError *error) {
  NSLog(@"Failed to get PIN2 retry count: %@", error);
}];

MoppLib can also send you notifications when retry counter changes. To get notifications, add observer for kMoppLibNotificationRetryCounterChanged

- (void)viewDidLoad {
  [super viewDidLoad];
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(retryCounterChanged) name:kMoppLibNotificationRetryCounterChanged object:nil];
}

- (void)retryCounterChanged {
  [MoppLibCardActions pin1RetryCountWithSuccess:^(NSNumber *count) {
    NSLog(@"PIN1 counter changed to %@", count);
  } failure:^(NSError *error) {
    NSLog(@"Error %@", error);
  }];
  
  [MoppLibCardActions pin2RetryCountWithSuccess:^(NSNumber *count) {
    NSLog(@"PIN2 counter changed to %@", count);
  } failure:^(NSError *error) {
    NSLog(@"Error %@", error);
  }];
  
  [MoppLibCardActions pukRetryCountWithSuccess:^(NSNumber *count) {
    NSLog(@"PUK counter changed to %@", count);
  } failure:^(NSError *error) {
    NSLog(@"Error %@", error);
  }];
}

Changing and unblocking PIN codes

With MoppLib it is also possible to change PIN codes in various ways.

Change PIN code using old PIN code is possible with changePin1WithPin1 or changePin2WithPin2 methods:

NSString *oldPin1 = "1349";
NSString *newPin1 = "8861";
[MoppLibPinActions changePin1To:newPin1 withOldPin1:oldPin1 success:^() {
  NSLog(@"PIN1 successfully change to %@", newPin1);
} failure:^(NSError* error) {
  NSLog(@"An error occured changing PIN1: %@", error);
}];

Another way to modify PIN codes is to use PUK code with changePin1WithPuk or changePin2WithPuk method:

NSString *puk = "123456";
NSString *newPin1 = "8861";
[MoppLibPinActions changePin1To:newPin1 withPuk:puk success:^() {
  NSLog(@"PIN1 successfully changed to %@", newPin1);
} failure:^(NSError* error) {
  NSLog(@"An error occured changing PIN1: %@", error);
}];

Similarily PUK code can be changed using old PUK code with changePuk method:

NSString *oldPuk = "564765";
NSString *newPuk = "132441";
[MoppLibPinActions changePukTo:newPuk withOldPuk:oldPuk success:^() {
  NSLog(@"Old PUK successfully change to %@", newPuk);
} failure:^(NSError* error) {
  NSLog(@"An error occured changing PUK: %@", error);
}];

Blocked PIN codes can be unblocked using unblockPin1 or unblockPin2 methods:

NSString *puk = "564765";
NSString *newPin1 = "3441";
[MoppLibPinActions unblockPin1WithPuk:puk newPin1:newPin1 success:^() {
  NSLog(@"PIN1 successfully unblocked");
} failure:^(NSError* error) {
  NSLog(@"An error occured unblocking PIN1: %@", error);
}];