roelderickx / connective-plugin-linux

A replacement for the Connective Plugin which is used on several websites to log in or sign documents using a card reader and an electronic identity card.
GNU General Public License v3.0
36 stars 2 forks source link

Error when creating itsme account (PIN_PAD_AVAILABLE) #7

Closed swertz closed 2 years ago

swertz commented 2 years ago

I was able to use the tool to connect to a web banking page using connective, but got an error when trying to create an itsme account. During account creation, the information could be read from my eID card successfully at first, and entering the PIN through the tkinter numpad worked fine, but later in the process it failed when trying to sign a document. In the firefox web console I saw this message:

stderr output from native app com.connective.signer: 
OUT {"error": {"code": 99, "id": 99, "message": "Error handling JSON message [{\"cmd\":\"PIN_PAD_AVAILABLE\",\"reader\":\"ACS ACR38U-CCID 00 00\",\"activationToken\":\"blah\",\"isRequest\":true}]. Unknown command [PIN_PAD_AVAILABLE]"}}
roelderickx commented 2 years ago

Thanks for your bug report and for adding the log, at least it helps to understand what went wrong.

This is bad news. I am sure there will be a bunch of other unimplemented commands once we get past PIN_PAD_AVAILABLE. There is only one way to find out: set up the client-server solution, sign the document and log all incoming and outgoing communication. Implementation should not be too hard once the log is available, provided there are no surprises involving encryption.

I wonder how many itsme accounts it will take to get this implemented and tested 😕 Any idea where we can sign documents for testing?

swertz commented 2 years ago

Thanks, I could use my spouse's windows PC to check that, but I can make no promise as to when I'll have the time...

(incidentally, itsme's support advises me to use a windows VM to create an account :roll_eyes: )

roelderickx commented 2 years ago

(incidentally, itsme's support advises me to use a windows VM to create an account 🙄 )

You're not the only one to have this non-solution proposed by itsme, see #1. Maybe I should ask access to their connective development environment and see how they react 😁

roelderickx commented 2 years ago

A quick peek in the executable reveals the following commands are not implemented in this version, but I don't think all of them are necessary to sign a document:

PIN_PAD_AVAILABLE is the first command, if the result is false then VERIFY_PIN will be probably be next to authenticate. However, the application is stateless so we are de-authenticated again at the end of VERIFY_PIN. Next is the computation of the signature using COMPUTE_SIGNATURE and/or COMPUTE_SIGN_CHALLENGE.

There is another way to implement this, without the client-server setup and without registering multiple itsme accounts. Since I already have the first message I can simply run the executable on windows and see what it returns. Once implemented you can try registering the itsme account again and see what the next message is. Since it will fail each time we can try over and over.

I'll have a look for an implementation of both the PIN_PAD_AVAILABLE and VERIFY_PIN messages to start with. The computation of the signature will take parameters, it remains to be seen what the message looks like.

roelderickx commented 2 years ago
swertz commented 2 years ago

Thanks! This time it went a bit further, it could read the certificates from the card, then I was asked for my PIN and it confirmed the PIN was correct, but it failed at the next step during document signature. Unfortunately the error does not seem to come from the python script but from the server:

XHRPOSThttps://bmid-esigner-prod.connective.eu/esig/signerapi/v1/signingfield/a2662d0f-5417-4c7a-af4d-f035b6d51ebd/signature
[HTTP/1.1 500 Internal Server Error 6006ms]

POST
    https://bmid-esigner-prod.connective.eu/esig/signerapi/v1/signingfield/a2662d0f-5417-4c7a-af4d-f035b6d51ebd/signature
Status
500
Internal Server Error
VersionHTTP/1.1
Transferred1.96 kB (20 B size)
Referrer Policystrict-origin-when-cross-origin

    HTTP/1.1 500 Internal Server Error

    Date: Wed, 19 Jan 2022 07:51:01 GMT

    Server: Connective Web Application Firewall

    Content-Type: text/plain; charset=UTF-8

    Content-Length: 20

    Cache-Control: must-revalidate, max-age=0, no-cache, no-store

    Pragma: no-cache

    Referrer-Policy: strict-origin-when-cross-origin

    Strict-Transport-Security: max-age=31536000

    X-Content-Type-Options: nosniff

    X-Content-Security-Policy: default-src 'self';

    X-Unique-id: -/-/20220119075059/YefC4y4QnyxgywVhGp5kAgAAAIE/-

    Cross-Origin-Opener-Policy: same-origin

    Vary: *

    Expires: 0

    Set-Cookie: osm.sid=05c400c588b14b57b204668dcb75f9be.3lpBMSYyWzQ7ShtybTMXQx2GxsodPC46X2L7i7tqxWHqFnRWGKSoDtrC4gJKBXuz8vJWPtFbJTyyvIit%2BH%2B2Ww%3D%3D; path=/; HttpOnly; secure

    X-Frame-Options: SAMEORIGIN

    Content-Security-Policy: report-uri /csp-report;default-src 'self' blob:;script-src https://apis.google.com https://www.dropbox.com http://static.hotjar.com https://static.hotjar.com https://script.hotjar.com https://www.googletagmanager.com https://tagmanager.google.com https://www.google-analytics.com https://ssl.google-analytics.com 'self' blob: 'unsafe-inline' 'unsafe-eval' 'report-sample';connect-src https://localhost:10443 https://*.connective.eu:* http://*.hotjar.com:* https://*.hotjar.com:* https://vc.hotjar.io:* wss://*.hotjar.com https://www.google-analytics.com https://graph.microsoft.com 'self' blob:;frame-src https://connective-bmidintegrationmock-app.azurewebsites.net https://uatsign.itsme.be https://sign.itsme.be https://accounts.google.com https://docs.google.com https://distribution.connective.eu https://distribution-acc.connective.eu https://distribution-test.connective.eu https://vars.hotjar.com https://ais-sas.swisscom.com 'self' blob: javascript:;img-src data: 'self' blob: *;font-src * data:;media-src * data:;style-src https://fonts.googleapis.com https://tagmanager.google.com 'self' blob: 'unsafe-inline';upgrade-insecure-requests;block-all-mixed-content

    Connection: close

    Accept
        application/json, text/plain, */*
    Accept-Encoding
        gzip, deflate, br
    Accept-Language
        en-GB,en;q=0.5
    Authorization
        Bearer Q2tw-hqNamYOseqGEWzjSPPqI7IOhLeOMb-C4ujPjdrYpcmlspAylpICjEVwWY6e
    Connection
        keep-alive
    Content-Length
        453
    Content-Type
        application/json;charset=utf-8
    Cookie
        osm.sid=05c400c588b14b57b204668dcb75f9be.3lpBMSYyWzQ7ShtybTMXQx2GxsodPC46X2L7i7tqxWHqFnRWGKSoDtrC4gJKBXuz8vJWPtFbJTyyvIit%2BH%2B2Ww%3D%3D
    DNT
        1
    Host
        bmid-esigner-prod.connective.eu
    Origin
        https://bmid-esigner-prod.connective.eu
    Referer
        https://bmid-esigner-prod.connective.eu/esig/signer/index.html?packageId=c6bae19a-cf2a-4523-a3c8-f750a3c6fabc&expiryTag=NDA3MDkwODgwMHwxMLAeD5z4Mn1iU1jHinsQqItskhJaKmLCghP-UQGQXQ&token=7i0HygUYtu5p5FByrPgPSP2NXinhjpTvMhgXs9DuCZCL22ZqIaYm3x-FNXMP2OPz&f2f=False
    Sec-Fetch-Dest
        empty
    Sec-Fetch-Mode
        cors
    Sec-Fetch-Site
        same-origin
    User-Agent
        Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0
XHRPOSThttps://bmid-esigner-prod.connective.eu/esig/signerapi/v1/signingfield/a2662d0f-5417-4c7a-af4d-f035b6d51ebd/signature
[HTTP/1.1 500 Internal Server Error 6006ms]

POST
    https://bmid-esigner-prod.connective.eu/esig/signerapi/v1/signingfield/a2662d0f-5417-4c7a-af4d-f035b6d51ebd/signature
Status
500
Internal Server Error
VersionHTTP/1.1
Transferred1.96 kB (20 B size)
Referrer Policystrict-origin-when-cross-origin

    HTTP/1.1 500 Internal Server Error

    Date: Wed, 19 Jan 2022 07:51:01 GMT

    Server: Connective Web Application Firewall

    Content-Type: text/plain; charset=UTF-8

    Content-Length: 20

    Cache-Control: must-revalidate, max-age=0, no-cache, no-store

    Pragma: no-cache

    Referrer-Policy: strict-origin-when-cross-origin

    Strict-Transport-Security: max-age=31536000

    X-Content-Type-Options: nosniff

    X-Content-Security-Policy: default-src 'self';

    X-Unique-id: -/-/20220119075059/YefC4y4QnyxgywVhGp5kAgAAAIE/-

    Cross-Origin-Opener-Policy: same-origin

    Vary: *

    Expires: 0

    Set-Cookie: osm.sid=05c400c588b14b57b204668dcb75f9be.3lpBMSYyWzQ7ShtybTMXQx2GxsodPC46X2L7i7tqxWHqFnRWGKSoDtrC4gJKBXuz8vJWPtFbJTyyvIit%2BH%2B2Ww%3D%3D; path=/; HttpOnly; secure

    X-Frame-Options: SAMEORIGIN

    Content-Security-Policy: report-uri /csp-report;default-src 'self' blob:;script-src https://apis.google.com https://www.dropbox.com http://static.hotjar.com https://static.hotjar.com https://script.hotjar.com https://www.googletagmanager.com https://tagmanager.google.com https://www.google-analytics.com https://ssl.google-analytics.com 'self' blob: 'unsafe-inline' 'unsafe-eval' 'report-sample';connect-src https://localhost:10443 https://*.connective.eu:* http://*.hotjar.com:* https://*.hotjar.com:* https://vc.hotjar.io:* wss://*.hotjar.com https://www.google-analytics.com https://graph.microsoft.com 'self' blob:;frame-src https://connective-bmidintegrationmock-app.azurewebsites.net https://uatsign.itsme.be https://sign.itsme.be https://accounts.google.com https://docs.google.com https://distribution.connective.eu https://distribution-acc.connective.eu https://distribution-test.connective.eu https://vars.hotjar.com https://ais-sas.swisscom.com 'self' blob: javascript:;img-src data: 'self' blob: *;font-src * data:;media-src * data:;style-src https://fonts.googleapis.com https://tagmanager.google.com 'self' blob: 'unsafe-inline';upgrade-insecure-requests;block-all-mixed-content

    Connection: close

    POST /esig/signerapi/v1/signingfield/a2662d0f-5417-4c7a-af4d-f035b6d51ebd/signature HTTP/1.1

    Host: bmid-esigner-prod.connective.eu

    User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0

    Accept: application/json, text/plain, */*

    Accept-Language: en-GB,en;q=0.5

    Accept-Encoding: gzip, deflate, br

    Referer: https://bmid-esigner-prod.connective.eu/esig/signer/index.html?packageId=c6bae19a-cf2a-4523-a3c8-f750a3c6fabc&expiryTag=NDA3MDkwODgwMHwxMLAeD5z4Mn1iU1jHinsQqItskhJaKmLCghP-UQGQXQ&token=7i0HygUYtu5p5FByrPgPSP2NXinhjpTvMhgXs9DuCZCL22ZqIaYm3x-FNXMP2OPz&f2f=False

    Authorization: Bearer Q2tw-hqNamYOseqGEWzjSPPqI7IOhLeOMb-C4ujPjdrYpcmlspAylpICjEVwWY6e

    Content-Type: application/json;charset=utf-8

    Content-Length: 453

    Origin: https://bmid-esigner-prod.connective.eu

    DNT: 1

    Connection: keep-alive

    Cookie: osm.sid=05c400c588b14b57b204668dcb75f9be.3lpBMSYyWzQ7ShtybTMXQx2GxsodPC46X2L7i7tqxWHqFnRWGKSoDtrC4gJKBXuz8vJWPtFbJTyyvIit%2BH%2B2Ww%3D%3D

    Sec-Fetch-Dest: empty

    Sec-Fetch-Mode: cors

    Sec-Fetch-Site: same-origin
roelderickx commented 2 years ago

Thanks for testing. It is probably too late now but can you see which was the latest request the python script processed?

swertz commented 2 years ago

Here it is:

stderr output from native app com.connective.signer: IN {"cmd":"COMPUTE_SIGNATURE","reader":"VASCO DIGIPASS 870 [CCID] 00 00","hash":"<hash>","isRequest":true}
stderr output from native app com.connective.signer: Card applet version: 17
stderr output from native app com.connective.signer: Card 0x6C delay required: 0 ms
stderr output from native app com.connective.signer: OUT {"pinRemainingAttempts": -1, "pinValid": true, "valid": true, "signature": "<hash>"}`
roelderickx commented 2 years ago

Ok thanks, the returned signature is wrong and the connective server seems to be unable to cope with this. I have some clue about how it is calculated but I cannot guarantee I'll find a solution. I'll try anyway. The good news is that you are probably only one message away from an itsme account 🙂

roelderickx commented 2 years ago

COMPUTE_SIGNATURE returns the correct signature now. I had to restructure the code somewhat, apparently we need to select the authentication algorithm before authenticating. The commands work for me, let's hope it is enough to register an itsme account.

swertz commented 2 years ago

With the latest changes, weirdly it failed earlier than before: I wasn't even asked for my PIN when signing the document... Here's the log:

stderr output from native app com.connective.signer: IN {"cmd":"READ_FILE","reader":"VASCO DIGIPASS 870 [CCID] 00 00","fileId":"3F00DF00503A","activationToken":"<token>","isRequest":true}
stderr output from native app com.connective.signer: Card applet version: 17
stderr output from native app com.connective.signer: Card 0x6C delay required: 0 ms
stderr output from native app com.connective.signer: OUT {"error": {"code": 5, "id": 5, "message": "Error reading file (Comm 0x6a87) (0xa4080c)"}}
roelderickx commented 2 years ago

That's weird idd, I think I didn't touch that code and I tested all messages before pushing to github. I'll have a look in the evening.

roelderickx commented 2 years ago

File id 3F00DF00503A is one of the certificates, it should always be readable according to the documentation on page 13. It works fine for me if I do the exact same request using test/protocoltest.html The error Error reading file (Comm 0x6a87) (0xa4080c) can only be caused by the select_file function. It is hard to tell if this is a bug in the code or simply a physical error reading your card (for example the card wasn't inserted properly, the chip was dirty or otherwise unreadable).

What I propose, to debug:

  1. Try to make the request using test/protocoltest.html: open the html file in your browser, click GET_READERS, Send request, READ_FILE, modify the fileId to 3F00DF00503A and click Send request again. The activationToken is not important for the Linux version.
  2. If this works without returning an error it was a temporary problem this morning and you can try signing the document at itsme again
  3. If it doesn't work then add more debugging in the select_file function. Add a new line containing sys.stderr.write('select_file returned %0x %0x\n' % (sw1, sw2)) at line number 299, after the call to send_apdu and before the if clause. Retry step 1 and report the browser log.

I am expecting a return value of 90 0, but if you look at the complete list of possible responses there are more valid possibilities. 61 xx or 9F xx for example.

swertz commented 2 years ago

Thanks, I've tried and it worked. I've then tried again to create an account, but ... it failed with a different message -_-

stderr output from native app com.connective.signer: IN {"cmd":"COMPUTE_SIGNATURE","reader":"VASCO DIGIPASS 870 [CCID] 00 00","hash":"<hash>","isRequest":true}
stderr output from native app com.connective.signer: OUT {"error": {"code": 7, "id": 7, "message": "Invalid hash [hash]; should be either 20, 32 or 64 bytes"}}
roelderickx commented 2 years ago

Thanks for testing. Is this a different kind of hash with a length different from 20, 32 or 64? I'll just disable the test then, let's assume the server sends correct data.

swertz commented 2 years ago

Ha, I should have checked the code, the length is fine (64) but the hash string was lowercase... Changing to [ c for c in value if (c.upper() not in '0123456789ABCDEF') ] here did the trick: https://github.com/roelderickx/connective-plugin-linux/blob/main/connective-backend.py#L552

I've finally been able to create an account :) Thanks a lot for your help!

roelderickx commented 2 years ago

Many thanks for confirming and for your patience! I'll update code as you suggested, who would have thought it is uppercase for compute authentication and lowercase for compute signature 😕