Fedict / eid-mw

eID Middleware (main repository)
GNU Lesser General Public License v3.0
198 stars 79 forks source link

New eID : bug with decrypting #193

Closed morayKevin closed 1 year ago

morayKevin commented 1 year ago

hello, we are having decryption problems with the new identity cards.

here is the source code:

PublicKey publicKey = eid.getPublicKey();
PrivateKey privateKey = eid.getSignaturePrivateKey();
Signature s = Signature.getInstance(eid.getUserCertificate().getSigAlgName());
byte[] encodedPublicKey = publicKey.getEncoded();
s.initSign(privateKey);
s.update(encodedPublicKey);
feedback.updateProgress("enterPin", 30);
byte[] signature = s.sign();
String base64Signature = new String(Base64.getEncoder().encode(signature));
Logger.writeLoggingLine("Signature Base64: " + base64Signature);

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
String sig = Arrays.toString(signature).substring(0, 16);
IvParameterSpec iv = new IvParameterSpec(sig.getBytes());
PBEKeySpec pbeKeySpec = new PBEKeySpec(sig.toCharArray());
SecretKey key = keyFac.generateSecret(pbeKeySpec);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
try (FileInputStream fis = new FileInputStream(encryptedImage);
   CipherInputStream cis = new CipherInputStream(fis, cipher)) {
   Logger.writeLoggingLine("Decrypting image");
   encryptedStreamToFile(cis);
} catch (IOException ex) {
   attempt++;
   continue;
}

I get the certificates this way:

ByteArrayInputStream bais = new ByteArrayInputStream("name = beid\nlibrary = c:\\WINDOWS\\system32\\beidpkcs11.dll".getBytes());
Security.addProvider(new SunPKCS11(bais));
keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, null);
certificateChain = keyStore.getCertificateChain(ALIAS_KEY);

I often encounter an IOexception when decrypting. I noticed that this problem is random. sometimes I have the problem, sometimes not, while I am using the same ID as well as the same encrypted file.

are you aware of this problem? how should i solve it?

yoe commented 1 year ago

Hi, and sorry for the late reply.

The eID card does not support encryption, only signing. There is an "Authorization" certificate and private key that is meant for authentication, and a "Signature" certificate and private key which is meant for legally-binding signatures.

Older cards used RSA keys, whose algorithm makes no distinction between signature operations and encryption operations, and so while the card (and the PKCS#11 module in support of the card) did not officially support it, you might have been able to make it work if you ignored the card spec and error codes and just went ahead anyway.

New cards, however, use elliptic curve-based keys (specifically, ECDSA on the NIST P-384 curve), which is an algorithm that can be used for signature operations but not for encryption (it's just not possible). As such, ignoring the card spec here will not get you anywhere because the algorithm itself does not support decrypting, and so it's normal you will get more error messages from your crypto library than with the old card.

In short, it is not supported, it was never supported, you should not do it, and the fact that you could do this earlier was simply because your crypto library was unable to understand the difference between "an RSA key meant only for signing" and "an RSA key meant for encryption" and could not throw errors when you used a key for a purpose for which the key was not provided, which is not the case anymore with new cards.

morayKevin commented 11 months ago

ok, I understand. Here is the process that we have put in place, do you have a solution to offer me?

We have implemented a process for electronic signature in our applications. To do this, we uploaded a signature (image) of the user to the database. This is encrypted with the user's identity card to ensure that it is not used for any other purpose. So when he wants to sign a document, we decrypt his image with this identity card.

I understand that this is not at all an intended use. Is it possible to have access to the signature (image) on the identity card? Or do you have a solution to suggest?

Thank you.

MatthiasValvekens commented 11 months ago

If you already need "live" access to the card during signing operations anyway, why not use the Signature key & certificate on the card to produce an actual qualified digital signature signature over the data you need, since that's exactly what it's intended for... :)

What file format are the documents you're signing? If it's PDF, there's tons of tooling available to do pretty much exactly this (FOSS, commercial and anything in between).

morayKevin commented 11 months ago

for 2 reasons:

I haven't found a solution to not asking for the pin code for each document.

but if you have a library, preferably free, which allows you to do this. I'm a taker 😀

MatthiasValvekens commented 11 months ago

the user really wants to have the image of their handwritten signature on the pdf.

That can be done by making the user draw a squiggle and using that as the appearance of the signature annotation, which is pretty common practice. (The legal value of the squiggle is almost nonexistent compared to the digital signature anyway, it's pretty much a purely skeuomorphic feature at this point.)

we do mass signing. this therefore means that we concatenate all the hashes of the documents. it is this result which is signed with the identity card

Mass signing PDF documents in bulk using eID isn't really possible technically, because, as you know---and for very good reasons---you need to authenticate for every signature separately. You could bundle all the PDFs in one huge file and sign that, but then if you want the signature to appear visibly on each sub-document, you also have to jump through some hoops. The spec disallows "multiplexing" signatures like this---FWIW, this limitation has been (and still is) the subject of a lot of debate in the PDF standardisation community.

(FWIW, I have a strong hunch that there are other issues with your threat model & cryptographic assumptions besides the ones pointed out here, but of course I don't have the full context, and I don't want to derail this thread even further... 😄 )

RE: PDF signing tooling, I maintain this library, which is FOSS and permissively licenced. There are many other FOSS tools available, e.g. iText, but depending on which option you pick you might have to be careful with the licencing conditions.


Anyway, now that we've established that encrypting data with the key pairs on a (new) eID is really a non-starter and only used to work because of a mathematical accident (read: design flaw) in RSA, this is getting pretty egregiously off topic. If you'd like to dig deeper, I'd be happy to continue our conversation over here. 🙂

yoe commented 10 months ago

ok, I understand. Here is the process that we have put in place, do you have a solution to offer me? [...] I understand that this is not at all an intended use. Is it possible to have access to the signature (image) on the identity card?

No; the handwritten signature is not available in digital form on the eID, and no plans to change this exist.

Or do you have a solution to suggest?

Disclaimer: all of the below is my personal opinion, and does not necessarily represent the opinion of anyone else, including either the Belgian government or my employer.

What you're currently doing is already not an eID signature. You just used the eID as an authentication method, and stored the handwritten signature in an end-to-end encrypted scheme so that you could not forge a signature without the user unlocking the image file. However, there is no way to link the created signature back to the user's eID; it is just a digital signature with an image, which claims to be authorized by the user but with no way to validate that claim with off-the-shelf software.

This creates a false sense that your signatures are eID signatures when in reality they're not.

I see two ways out:

  1. You could make it clear that these are not eID signatures by encrypting the signature image to a password (using symmetric encryption), and requiring the eID only during enrollment and/or as a second factor for authentication. This does not lose you any functionality vis-a-vis your current implementation, but would have the downside of changing your authentication method.

  2. You could drop the whole handwritten signature image thing and copy the photo of the user from their eID into the PDF file, accompanied by a text like "digitally signed by <name of user as copied from eID>"? There is little legal value in a digital version of a handwritten signature anyway, so since you're (presumably) already creating a (hopefully qualified) digital signature, that should have preference in a digital file anyway.

MatthiasValvekens commented 10 months ago

There is little legal value in a digital version of a handwritten signature anyway, so since you're (presumably) already creating a (hopefully qualified) digital signature, that should have preference in a digital file anyway.

I agree with this (and everything else you said), but OP is apparently already using a nonstandard way of "mass signing" a bunch of documents at once by hashing multiple docs at once, and I'm not sure that would stand up to scrutiny.

IMHO, if you're bulk signing a bunch of documents but you still need each of them to have an individual signature, you're solving the wrong problem. If you care about qualified signatures as a framework, you either sign them all individually according to the rules, or you admit that the individual signatures don't really matter in the end and just merge the whole bunch into one big PDF, then sign that. If you don't care about qualified signatures, then the limitations of the eID are functionally irrelevant and you might as well just put in a picture/squiggle/....

But I recognise that opinions diverge on this issue---I've lost count of how many times we argued about this in standards committee meetings on PDF signing...

yoe commented 10 months ago

I agree with this (and everything else you said), but OP is apparently already using a nonstandard way of "mass signing" a bunch of documents at once by hashing multiple docs at once, and I'm not sure that would stand up to scrutiny.

Well, yes. That too. I'm working off the assumption that OP talked to a lawyer before implementing this very non-standard way of doing things, but then I recognize that my assumptions may be wrong.

morayKevin commented 10 months ago

I completely agree that our "electronic signature" probably has no legal value. But I still have an XML file with the signature information.

`

3082060A308203F2A00302010202102907385EA678E3200C6........6FBB923ECD 9a331aa6b228add35718c3ba382dda0ee138c1d0dcb74c37fb9a79cfae4bdc1752816b0c4a31ae318cef368e3c310c40cf5016a54e045b631f574411ad9af4c9
<rootCertificate>3082058E30820376A00302010202084.....40A46F801B4BDE3B517E8D18</rootCertificate>
<signTimestamp>2020.05.11 @ 14:32:06 CEST</signTimestamp>
<signatory>XXXX PPPP</signatory>
<signatureKey>4DB47CECD8C9CCC2B365942B.....82A11E942</signatureKey>
<ssin>75083014558</ssin>
<userCertificate>3082068C30820474A....320AE0710520</userCertificate>

`

and so, yes we need software allowing validation. what is its necessity? the document is still subsequently sent on paper.

but let's imagine that I want to make a real electronic signature, sending decisions by ebox for example. once the merged PDF is signed, it will no longer be possible for me to cut it into X PDF?

morayKevin commented 10 months ago

Here, you can find more information on the signing method. https://www.smalsresearch.be/tools/smalsbesign/