Dear all,

In another topic, I learned that Nitrokey Start supports ECDH Nitrokey Start documentation.

So I tried to run a ECDH computation.

First I created an Alice ECDH key on my Nitrokey Start based on NIST P256.

  • ----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----

Bob computed a random value

and Bob get his ephemeral ECDH public key.


So according to the Open PGP Card Specification 3.4.1 page 68, I need to encapsulate this ExternalPublicKey and send it through a Decipher Command:

Decipher Command sent : 00 2a 80 86 : (Decipher) 48 : Lc (length) a6 : ECDH (Cipher DO) 46 : Length 7f49 : Public Key DO 43 Length 86 : External Public Key 41 : Length 046131fc76fc7ab40642b2fa32712f61b88048c1140cc28c67c20bcb939c18670cc85dcd947bc53ceb8885025d9a526cf4acb6aab71aaf4ee831503898830a268d00
: uncompressed raw format

But I received the value :


Which is a point on the NIST P256 curve.
But I thought i will rather receive the Bob random value.

I tried the encipher command, but receive a 6F00 status byte.

I can’t see where is my mistake could you help me ?

Many thanks in advance.

Best regards.

Hi @PhilC!

I cannot go deeper into the topic right now, but I can give a quick hints regarding the debugging:

  1. Have you tried peeking at the GnuPG’s scdaemon output while executing similar operation?
  2. Another thing possibly helpful might lie in associated project’s tests:
  3. Perhaps Nitrokey Start’s implementation is a bit different than described in OpenPGP v3.4 standard (I would guess it was written after initial v3.0/v3.1). I am not aware of any direct differences, but each device has its own driver in GnuPG/OpenSC implementation, where they could be investigated.
  4. You could try to look into another OpenPGP v3.4 implementation, like:
  5. You can review the Nitrokey Start source code implementation here:

Kind regards

1 Like

Hi @szszszsz,

Many thanks for your detailed answers.

I haven’t resolved the problem yet, but I believe i should be able to do it with your previous answers.

Regarding point 5 : I see that the return is really the point on the curve. So I have correctly set the command.

So in order to retrieve the share secret, I should only consider the r.x response for my result. Unfortunately, it isn’t equal to my Bob random, then I need to dig a little bit more. :slight_smile:
I thought that my “Bob computation” was ok, but I will check again.

Regarding point 2 : Could you check the fixture, because AFAIU it only covers RSA decryption.

And very cosmetic point, I was not aware of Freshen, but since it is no more maintained I understand why. Have you already considered Aloe ? I moved from Lettuce to Aloe without noticeable troubles and you can export your results to xunit format.
Aren’t you stuck with python 2.x with freshen ?

Best regards.

Euh … SHAME ON ME !!!

Obviously everything is fine, and I should go back to my studies :frowning:

It’s obvious that I won’t receive Bob random value !! That’s the Bob’s private key !!
Well in this example, I forgot to compute the Bob’s result using the Alice’s public key.

And obviously I get the same point

Bob secret point : X: 0xa27b2ede431c7f6678a873936615049f28ece6f85eb6875ddc909cd242cc0c71
Y: 0x7e36d16abc01b4cea40455021ed3d9137ae4c1e78823835ac9f374b424c1aec1

Afterward, I just have to get the Rx part to enter my favorites hash function and kdf.

We can obviously close this ticket, and I just have to found the nearest mouse hole.


Thank you for the suggestions! Made proper tickets to look into this further:

I am glad you have figured out solution to your problem! Sometimes just writing down the question helps :slight_smile: