“Lets pretend to be developers” 🙂

Well, that 500 server error appears to be an issue my side.

I will investigate.

EDIT: Looks like the HTTP timeout you two are experiencing is related to a backend process that’s failed - it’s actually timing out on a connection to our internal cryptographic API.

2 Likes

All fixed: Internal API appears to have stopped responding and a kick in the guts fixed it.

I should probably put a weekly reboot on these things.

2 Likes

That must have been the fix, everything works for me now. Thank you!

1 Like

We’ve put a change process in place for updates - I’ve disabled automatic updates on production servers (which were somehow enabled… I blame Ubuntu 20.04) and will manually update them weekly.

No!!! If this thing is failing there is a reason. If you fix it then it won’t fail. If you just reboot it on a scheduled basis you are just hiding a problem.

It is a matter of professional pride for me that I fix problems not just sweep them under the rug.

Now if it is failing in something you didn’t write, and you don’t have the source code for then it becomes a lot harder.

It’s not failing because of anything I wrote. It’s literally docker being a pain in the arse on update and not restarting the containers.

The fix is to update production servers manually and have scheduled downtime for these things. Which will be at 12:00am Mondays at GMT0.

Fair enough.

Docker is not my favourite tool.

In fact I usually avoid using it.

Pffft IT types - always making it sound so technical :face_with_monocle:

1 Like

I’m aiming to move a fair bit to Kubernetes soonish.

2 Likes

Awesome no more ERROR 500! thanks fragger.

Now back to my broken code, i get

"pcd-response": "error"

Again have tried caps and no caps as well as LSB and MSB and still get the above.

1 Like

Are you including the pcd-challenge as received from get-challenge? Picc-challenge is as received from the chip, no msb/LSB bullshit. Same for the uid iirc. They’re already flipped in the database.

I think it would make sense for me to share my code right now.

getChallenge
private string getPICCChallenge()
        {
            string challenge;
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(baseURL + getChallengeEndpoint);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method = "POST";

            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                Dictionary<string, string> post = new Dictionary<string, string>
                {
                    {"api-key", apikey }
                };

                string json = JsonConvert.SerializeObject(post, Formatting.Indented);

                streamWriter.Write(json);
            }

            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                challenge = streamReader.ReadToEnd();
            }

            var data = (JObject)JsonConvert.DeserializeObject(challenge);

            return data.First.First.ToString();

        }
getUID
private string getUID()
        {
            using (var ctx = contextFactory.Establish(SCardScope.System))
            {
                using (var isoReader = new IsoReader(ctx, comboBox1.Text, SCardShareMode.Shared, SCardProtocol.Any, false))
                {

                    var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol)
                    {
                        CLA = 0xFF, // Class
                        Instruction = InstructionCode.GetData,
                        P1 = 0x00, // Parameter 1
                        P2 = 0x00, // Parameter 2
                        Le = 0x07 // Expected length of the returned data
                    };

                    var response = isoReader.Transmit(apdu);
                    var array = response.GetData();

                    return BitConverter.ToString(array).Replace("-", string.Empty);
                }
            }
        }
getPCDChallenge
private string getPCDChallenge()
        {
            using (var ctx = contextFactory.Establish(SCardScope.System))
            {
                using (var isoReader = new IsoReader(ctx, comboBox1.Text, SCardShareMode.Shared, SCardProtocol.Any, false))
                {
                    var apdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol)
                    {
                        CLA = 0x90, // Class
                        INS = 0x71,
                        P1 = 0x00, // Parameter 1
                        P2 = 0x00, // Parameter 2
                        Data = new byte[] { 0x02, 0x00 },
                        Le = 0x00
                    };

                    var response = isoReader.Transmit(apdu);
                    var array = response.GetData();

                    return BitConverter.ToString(array).Replace("-", string.Empty).ToLower();
                }
            }
        }

At this point my struct contains

auth.PICCUID = "04XXXXXXXXXXXX"
auth.PCDchallenge = "58EB612FC45FB06A9D473F994589B1D1"
auth.PICCchallenge = "154ad56c251753b809b829dd0bfb8e69"
auth.PCDresponse = ""
getPCDResponse
private string getPCDResponse(AUTH auth)
        {
            string response;
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(baseURL + pcdChallengeEndpoint);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method = "POST";

            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                Dictionary<string, string> post = new Dictionary<string, string>
                {
                    {"picc-uid", auth.PICCUID},
                    {"picc-challenge", auth.PICCchallenge},
                    {"pcd-challenge", auth.PCDchallenge}
                };

                string json = JsonConvert.SerializeObject(post);

                streamWriter.Write(json);
            }

            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                response = streamReader.ReadToEnd();
            }

            var data = (JObject)JsonConvert.DeserializeObject(response);

            return data.First.First.ToString();
        }

At this point my struct contains

auth.PICCUID = "04XXXXXXXXXXXX"
auth.PCDchallenge = "58EB612FC45FB06A9D473F994589B1D1"
auth.PICCchallenge = "154ad56c251753b809b829dd0bfb8e69"
auth.PCDresponse = "error"

Ok so im stuck, double and triple checked everything and still can only get error RIP my weekend

I have also tried to use the select command as well but the chipscanlib seems to show it is only needed for the apex. I get a response 6A 82 which is File not found.

Any other ideas im willing to try.

Well fuck it :sob:

Heres the visual studio project for anyone who wants to try, i give up. All you need to add is your apikey.

VivokeyACR.zip (509.4 KB)

1 Like

So just asked a developer friend to take a look, she wrote here own code (C#) based on the documentation and she couldn’t get it to work either.

So what now, well either were not getting the challenge from the api / picc properly or the api is expecting something unexpected.

Any input would be great.

we’ll take a peek at it soon… sorry for the hassle @Devilclarke, but your struggles are appreciated… if it’s this difficult then something needs to be smoothed out.

2 Likes

Hey no problem, I don’t mind having these issues as long as we figure it out in the end. Once we get it working I’ll throw the solution up for a chip scan demo in C# :slight_smile:

2 Likes

I believe sending an ISOSelectFile command is a prerequisite to sending the AuthenticateEV2First command AND skipping the ISOSelectFile command would cause an incorrect “key #2” to be used for mutual authentication. I think this is the issue you are facing. Here is a snippet from my code, hope this helps.

(Obtain UID...)
write:  00 A4 04 0C 07 D2 76 00 00 85 01 01 00 <- ISOSelectFile
PICC:   90 00
write:  90 71 00 00 02 02 00 00 <-AuthenticateEV2First
Screenshots: Beware Dark Theme Users

Structure

Structure 413 DNA

Information about these commands can be found in the PDF datasheet. The screenshots from both the 424dna and 413dna datasheets should help explain what I am referring to.

2 Likes

Ok so in a previous post I said I had issues using the select command, I had structured it incorrectly and that is why. I now get 90 00 response from the select command.

getPCDChallenge
private string getPCDChallenge()
        {
            using (var ctx = contextFactory.Establish(SCardScope.System))
            {
                using (var isoReader = new IsoReader(ctx, comboBox1.Text, SCardShareMode.Shared, SCardProtocol.Any, false))
                {

                    var selectFile = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any)
                    {
                        CLA = 0x00,
                        INS = 0xA4,
                        P1 = 0x04,
                        P2 = 0x0C,
                        Data = new byte[] { 0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01 }
                    };

                    var response1 = isoReader.Transmit(selectFile);

                    var AuthenticateEV2First = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol)
                    {
                        CLA = 0x90,
                        INS = 0x71,
                        P1 = 0x00, 
                        P2 = 0x00, 
                        Data = new byte[] { 0x02, 0x00 },
                        Le = 0x00
                    };

                    var response = isoReader.Transmit(AuthenticateEV2First);
                    var array = response.GetData();

                    return BitConverter.ToString(array).Replace("-", string.Empty);
                }
            }
        }

still getting an error response from getPCDResponse